@aehrc/smart-forms-renderer 1.2.8 → 1.2.9

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 (64) hide show
  1. package/lib/components/FormComponents/AttachmentItem/AttachmentField.js +3 -2
  2. package/lib/components/FormComponents/AttachmentItem/AttachmentField.js.map +1 -1
  3. package/lib/components/FormComponents/BooleanItem/BooleanField.d.ts +2 -1
  4. package/lib/components/FormComponents/BooleanItem/BooleanField.js +6 -4
  5. package/lib/components/FormComponents/BooleanItem/BooleanField.js.map +1 -1
  6. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js +8 -8
  7. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.js.map +1 -1
  8. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.js +11 -11
  9. package/lib/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.js.map +1 -1
  10. package/lib/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateField.js +2 -1
  11. package/lib/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateField.js.map +1 -1
  12. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomTimeField.js +2 -1
  13. package/lib/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomTimeField.js.map +1 -1
  14. package/lib/components/FormComponents/DecimalItem/DecimalField.js +2 -1
  15. package/lib/components/FormComponents/DecimalItem/DecimalField.js.map +1 -1
  16. package/lib/components/FormComponents/IntegerItem/IntegerField.js +2 -1
  17. package/lib/components/FormComponents/IntegerItem/IntegerField.js.map +1 -1
  18. package/lib/components/FormComponents/Item.styles.d.ts +1 -1
  19. package/lib/components/FormComponents/Item.styles.js +1 -1
  20. package/lib/components/FormComponents/ItemParts/AccessibleFeedback.d.ts +7 -0
  21. package/lib/components/FormComponents/ItemParts/AccessibleFeedback.js +7 -0
  22. package/lib/components/FormComponents/ItemParts/AccessibleFeedback.js.map +1 -0
  23. package/lib/components/FormComponents/ItemParts/CheckboxFormGroup.js +4 -2
  24. package/lib/components/FormComponents/ItemParts/CheckboxFormGroup.js.map +1 -1
  25. package/lib/components/FormComponents/ItemParts/ClearButtonAdornment.js +12 -12
  26. package/lib/components/FormComponents/ItemParts/ClearButtonAdornment.js.map +1 -1
  27. package/lib/components/FormComponents/ItemParts/RadioFormGroup.d.ts +1 -1
  28. package/lib/components/FormComponents/ItemParts/RadioFormGroup.js +5 -3
  29. package/lib/components/FormComponents/ItemParts/RadioFormGroup.js.map +1 -1
  30. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.js +8 -8
  31. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.js.map +1 -1
  32. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.js +3 -3
  33. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.js.map +1 -1
  34. package/lib/components/FormComponents/QuantityItem/QuantityField.js +2 -1
  35. package/lib/components/FormComponents/QuantityItem/QuantityField.js.map +1 -1
  36. package/lib/components/FormComponents/SliderItem/SliderField.js +4 -2
  37. package/lib/components/FormComponents/SliderItem/SliderField.js.map +1 -1
  38. package/lib/components/FormComponents/StringItem/StringField.js +2 -1
  39. package/lib/components/FormComponents/StringItem/StringField.js.map +1 -1
  40. package/lib/components/FormComponents/TextItem/TextField.js +2 -1
  41. package/lib/components/FormComponents/TextItem/TextField.js.map +1 -1
  42. package/lib/components/FormComponents/UrlItem/UrlField.js +2 -1
  43. package/lib/components/FormComponents/UrlItem/UrlField.js.map +1 -1
  44. package/package.json +4 -4
  45. package/src/components/FormComponents/AttachmentItem/AttachmentField.tsx +7 -2
  46. package/src/components/FormComponents/BooleanItem/BooleanField.tsx +12 -3
  47. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.tsx +2 -3
  48. package/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.tsx +3 -3
  49. package/src/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateField.tsx +2 -1
  50. package/src/components/FormComponents/DateTimeItems/CustomDateTimeItem/CustomTimeField.tsx +6 -3
  51. package/src/components/FormComponents/DecimalItem/DecimalField.tsx +2 -1
  52. package/src/components/FormComponents/IntegerItem/IntegerField.tsx +2 -1
  53. package/src/components/FormComponents/Item.styles.ts +1 -1
  54. package/src/components/FormComponents/ItemParts/AccessibleFeedback.tsx +35 -0
  55. package/src/components/FormComponents/ItemParts/CheckboxFormGroup.tsx +10 -2
  56. package/src/components/FormComponents/ItemParts/ClearButtonAdornment.tsx +22 -23
  57. package/src/components/FormComponents/ItemParts/RadioFormGroup.tsx +11 -3
  58. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerOptionField.tsx +2 -3
  59. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceSelectAnswerValueSetField.tsx +2 -3
  60. package/src/components/FormComponents/QuantityItem/QuantityField.tsx +2 -1
  61. package/src/components/FormComponents/SliderItem/SliderField.tsx +10 -2
  62. package/src/components/FormComponents/StringItem/StringField.tsx +2 -1
  63. package/src/components/FormComponents/TextItem/TextField.tsx +2 -1
  64. package/src/components/FormComponents/UrlItem/UrlField.tsx +2 -1
@@ -14,29 +14,28 @@ export function ClearButtonAdornment(props: ClearButtonAdornmentProps) {
14
14
  }
15
15
 
16
16
  return (
17
- <span title="Clear">
18
- <IconButton
19
- aria-label="Clear"
20
- size="small"
21
- tabIndex={-1}
22
- onClick={(e) => {
23
- onClear();
17
+ <IconButton
18
+ aria-hidden="true"
19
+ tabIndex={-1}
20
+ size="small"
21
+ title="Clear"
22
+ onClick={(e) => {
23
+ onClear();
24
24
 
25
- // Manually re-focus the input field
26
- const input = e.currentTarget.closest('.MuiOutlinedInput-root')?.querySelector('input');
27
- if (input) {
28
- input.focus();
29
- }
30
- }}
31
- onMouseDown={(e) => {
32
- e.preventDefault(); // Prevent the button from stealing focus
33
- }}
34
- className="StandardTextField-clearIndicator"
35
- sx={{
36
- p: 0.5
37
- }}>
38
- <ClearIcon fontSize="small" />
39
- </IconButton>
40
- </span>
25
+ // Manually re-focus the input field
26
+ const input = e.currentTarget.closest('.MuiOutlinedInput-root')?.querySelector('input');
27
+ if (input) {
28
+ input.focus();
29
+ }
30
+ }}
31
+ onMouseDown={(e) => {
32
+ e.preventDefault(); // Prevent the button from stealing focus
33
+ }}
34
+ className="StandardTextField-clearIndicator"
35
+ sx={{
36
+ p: 0.5
37
+ }}>
38
+ <ClearIcon fontSize="small" />
39
+ </IconButton>
41
40
  );
42
41
  }
@@ -1,14 +1,15 @@
1
1
  import Box from '@mui/material/Box';
2
2
  import RadioGroup from '@mui/material/RadioGroup';
3
3
  import type { QuestionnaireItem, QuestionnaireItemAnswerOption } from 'fhir/r4';
4
- import type { ReactNode } from 'react';
4
+ import React, { ReactNode } from 'react';
5
5
  import { ChoiceItemOrientation } from '../../../interfaces/choice.enum';
6
6
  import { useRendererConfigStore } from '../../../stores';
7
7
  import { getChoiceOrientation } from '../../../utils/choice';
8
- import { StyledRequiredTypography } from '../Item.styles';
8
+ import { StyledFeedbackTypography } from '../Item.styles';
9
9
  import ClearInputButton from './ClearInputButton';
10
10
  import ExpressionUpdateFadingIcon from './ExpressionUpdateFadingIcon';
11
11
  import RadioOptionList from './RadioOptionList';
12
+ import AccessibleFeedback from './AccessibleFeedback';
12
13
 
13
14
  interface ChoiceRadioGroupProps {
14
15
  qItem: QuestionnaireItem;
@@ -44,6 +45,8 @@ function RadioFormGroup(props: ChoiceRadioGroupProps) {
44
45
 
45
46
  const orientation = getChoiceOrientation(qItem) ?? ChoiceItemOrientation.Vertical;
46
47
 
48
+ const feedbackId = qItem.type + '-' + qItem.linkId + '-feedback';
49
+
47
50
  return (
48
51
  <>
49
52
  <Box
@@ -64,6 +67,7 @@ function RadioFormGroup(props: ChoiceRadioGroupProps) {
64
67
  ? { 'aria-labelledby': 'label-' + qItem.linkId }
65
68
  : { 'aria-label': qItem.text ?? 'Unnamed radio group' })}
66
69
  aria-readonly={readOnly && readOnlyVisualStyle === 'readonly'}
70
+ aria-describedby={feedback ? feedbackId : undefined}
67
71
  row={orientation === ChoiceItemOrientation.Horizontal}
68
72
  sx={inputsFlexGrow ? { width: '100%', flexWrap: 'nowrap' } : {}}
69
73
  onChange={(e) => {
@@ -93,7 +97,11 @@ function RadioFormGroup(props: ChoiceRadioGroupProps) {
93
97
  <ClearInputButton buttonShown={!!valueRadio} readOnly={readOnly} onClear={onClear} />
94
98
  </Box>
95
99
 
96
- {feedback ? <StyledRequiredTypography>{feedback}</StyledRequiredTypography> : null}
100
+ {feedback ? (
101
+ <AccessibleFeedback id={feedbackId}>
102
+ <StyledFeedbackTypography>{feedback}</StyledFeedbackTypography>
103
+ </AccessibleFeedback>
104
+ ) : null}
97
105
  </>
98
106
  );
99
107
  }
@@ -27,8 +27,8 @@ import type {
27
27
  PropsWithRenderingExtensionsAttribute
28
28
  } from '../../../interfaces/renderProps.interface';
29
29
  import { useRendererConfigStore } from '../../../stores';
30
- import { StyledRequiredTypography } from '../Item.styles';
31
30
  import DisplayUnitText from '../ItemParts/DisplayUnitText';
31
+ import AccessibleFeedback from '../ItemParts/AccessibleFeedback';
32
32
 
33
33
  interface OpenChoiceSelectAnswerOptionFieldProps
34
34
  extends PropsWithIsTabledAttribute,
@@ -83,6 +83,7 @@ function OpenChoiceSelectAnswerOptionField(props: OpenChoiceSelectAnswerOptionFi
83
83
  textFieldWidth={textFieldWidth}
84
84
  isTabled={isTabled}
85
85
  placeholder={entryFormat || displayPrompt}
86
+ helperText={<AccessibleFeedback>{feedback}</AccessibleFeedback>}
86
87
  {...params}
87
88
  slotProps={{
88
89
  input: {
@@ -99,8 +100,6 @@ function OpenChoiceSelectAnswerOptionField(props: OpenChoiceSelectAnswerOptionFi
99
100
  />
100
101
  )}
101
102
  />
102
-
103
- {feedback ? <StyledRequiredTypography>{feedback}</StyledRequiredTypography> : null}
104
103
  </>
105
104
  );
106
105
  }
@@ -28,8 +28,8 @@ import type {
28
28
  import type { Coding, QuestionnaireItem } from 'fhir/r4';
29
29
  import type { TerminologyError } from '../../../hooks/useValueSetCodings';
30
30
  import { useRendererConfigStore } from '../../../stores';
31
- import { StyledRequiredTypography } from '../Item.styles';
32
31
  import DisplayUnitText from '../ItemParts/DisplayUnitText';
32
+ import AccessibleFeedback from '../ItemParts/AccessibleFeedback';
33
33
 
34
34
  interface OpenChoiceSelectAnswerValueSetFieldProps
35
35
  extends PropsWithIsTabledAttribute,
@@ -88,6 +88,7 @@ function OpenChoiceSelectAnswerValueSetField(props: OpenChoiceSelectAnswerValueS
88
88
  textFieldWidth={textFieldWidth}
89
89
  isTabled={isTabled}
90
90
  placeholder={entryFormat || displayPrompt}
91
+ helperText={<AccessibleFeedback>{feedback}</AccessibleFeedback>}
91
92
  {...params}
92
93
  slotProps={{
93
94
  input: {
@@ -110,8 +111,6 @@ function OpenChoiceSelectAnswerValueSetField(props: OpenChoiceSelectAnswerValueS
110
111
  {terminologyError.answerValueSet}
111
112
  </Typography>
112
113
  ) : null}
113
-
114
- {feedback ? <StyledRequiredTypography>{feedback}</StyledRequiredTypography> : null}
115
114
  </>
116
115
  );
117
116
  }
@@ -22,6 +22,7 @@ import DisplayUnitText from '../ItemParts/DisplayUnitText';
22
22
  import { ClearButtonAdornment } from '../ItemParts/ClearButtonAdornment';
23
23
  import ExpressionUpdateFadingIcon from '../ItemParts/ExpressionUpdateFadingIcon';
24
24
  import { StandardTextField } from '../Textfield.styles';
25
+ import AccessibleFeedback from '../ItemParts/AccessibleFeedback';
25
26
 
26
27
  interface QuantityFieldProps extends PropsWithIsTabledAttribute {
27
28
  linkId: string;
@@ -104,7 +105,7 @@ function QuantityField(props: QuantityFieldProps) {
104
105
  )
105
106
  }
106
107
  }}
107
- helperText={feedback}
108
+ helperText={<AccessibleFeedback>{feedback}</AccessibleFeedback>}
108
109
  data-test="q-item-quantity-field"
109
110
  />
110
111
  );
@@ -22,8 +22,9 @@ import Stack from '@mui/material/Stack';
22
22
  import SliderLabels from './SliderLabels';
23
23
  import SliderDisplayValue from './SliderDisplayValue';
24
24
  import { useRendererConfigStore } from '../../../stores';
25
- import { StyledRequiredTypography } from '../Item.styles';
25
+ import { StyledFeedbackTypography } from '../Item.styles';
26
26
  import { StandardSlider } from './Slider.styles';
27
+ import AccessibleFeedback from '../ItemParts/AccessibleFeedback';
27
28
 
28
29
  interface SliderFieldProps extends PropsWithIsTabledAttribute {
29
30
  linkId: string;
@@ -69,6 +70,8 @@ function SliderField(props: SliderFieldProps) {
69
70
 
70
71
  const hasLabels = !!(minLabel || maxLabel);
71
72
 
73
+ const feedbackId = itemType + '-' + linkId + '-feedback';
74
+
72
75
  return (
73
76
  <>
74
77
  <Stack sx={{ ...sliderSx }}>
@@ -95,12 +98,17 @@ function SliderField(props: SliderFieldProps) {
95
98
  disabled={readOnly && readOnlyVisualStyle === 'disabled'}
96
99
  readOnly={readOnly && readOnlyVisualStyle === 'readonly'}
97
100
  aria-readonly={readOnly && readOnlyVisualStyle === 'readonly'}
101
+ aria-describedby={feedback ? feedbackId : undefined}
98
102
  valueLabelDisplay="auto"
99
103
  data-test="q-item-slider-field"
100
104
  />
101
105
  </Stack>
102
106
 
103
- {feedback ? <StyledRequiredTypography>{feedback}</StyledRequiredTypography> : null}
107
+ {feedback ? (
108
+ <AccessibleFeedback id={feedbackId}>
109
+ <StyledFeedbackTypography>{feedback}</StyledFeedbackTypography>
110
+ </AccessibleFeedback>
111
+ ) : null}
104
112
  </>
105
113
  );
106
114
  }
@@ -25,6 +25,7 @@ import ItemRepopulateButton from '../ItemParts/ItemRepopulateButton';
25
25
  import type { RenderingExtensions } from '../../../hooks/useRenderingExtensions';
26
26
  import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
27
27
  import { StandardTextField } from '../Textfield.styles';
28
+ import AccessibleFeedback from '../ItemParts/AccessibleFeedback';
28
29
 
29
30
  interface StringFieldProps extends PropsWithIsTabledAttribute {
30
31
  qItem: QuestionnaireItem;
@@ -90,7 +91,7 @@ function StringField(props: StringFieldProps) {
90
91
  )
91
92
  }
92
93
  }}
93
- helperText={feedback}
94
+ helperText={<AccessibleFeedback>{feedback}</AccessibleFeedback>}
94
95
  data-test="q-item-string-field"
95
96
  />
96
97
  );
@@ -23,6 +23,7 @@ import ExpressionUpdateFadingIcon from '../ItemParts/ExpressionUpdateFadingIcon'
23
23
  import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
24
24
  import type { RenderingExtensions } from '../../../hooks/useRenderingExtensions';
25
25
  import ItemRepopulateButton from '../ItemParts/ItemRepopulateButton';
26
+ import AccessibleFeedback from '../ItemParts/AccessibleFeedback';
26
27
 
27
28
  interface TextFieldProps {
28
29
  qItem: QuestionnaireItem;
@@ -79,7 +80,7 @@ function TextField(props: TextFieldProps) {
79
80
  )
80
81
  }
81
82
  }}
82
- helperText={feedback}
83
+ helperText={<AccessibleFeedback>{feedback}</AccessibleFeedback>}
83
84
  data-test="q-item-text-field"
84
85
  />
85
86
  );
@@ -22,6 +22,7 @@ import { StandardTextField } from '../Textfield.styles';
22
22
  import { useRendererConfigStore } from '../../../stores';
23
23
  import DisplayUnitText from '../ItemParts/DisplayUnitText';
24
24
  import { ClearButtonAdornment } from '../ItemParts/ClearButtonAdornment';
25
+ import AccessibleFeedback from '../ItemParts/AccessibleFeedback';
25
26
 
26
27
  interface UrlFieldProps extends PropsWithIsTabledAttribute {
27
28
  linkId: string;
@@ -81,7 +82,7 @@ function UrlField(props: UrlFieldProps) {
81
82
  )
82
83
  }
83
84
  }}
84
- helperText={feedback}
85
+ helperText={<AccessibleFeedback>{feedback}</AccessibleFeedback>}
85
86
  data-test="q-item-url-field"
86
87
  />
87
88
  );