@pingux/astro 1.36.1 → 1.36.2-alpha.1

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 (60) hide show
  1. package/lib/cjs/components/CheckboxField/CheckboxField.js +7 -2
  2. package/lib/cjs/components/CheckboxField/CheckboxField.test.js +16 -0
  3. package/lib/cjs/components/ComboBoxField/ComboBoxField.js +5 -2
  4. package/lib/cjs/components/ComboBoxField/ComboBoxField.test.js +20 -0
  5. package/lib/cjs/components/EnvironmentBreadcrumb/EnvironmentBreadcrumb.js +18 -8
  6. package/lib/cjs/components/EnvironmentBreadcrumb/EnvironmentBreadcrumb.test.js +16 -0
  7. package/lib/cjs/components/FieldHelperText/FieldHelperText.js +8 -3
  8. package/lib/cjs/components/FileInputField/FileInputField.js +6 -2
  9. package/lib/cjs/components/FileInputField/FileInputField.test.js +15 -0
  10. package/lib/cjs/components/FileInputField/FileItem.js +5 -2
  11. package/lib/cjs/components/ImageUploadField/ImageUploadField.js +19 -6
  12. package/lib/cjs/components/ImageUploadField/ImageUploadFieldBase.js +4 -3
  13. package/lib/cjs/components/LinkSelectField/LinkSelectField.js +13 -3
  14. package/lib/cjs/components/LinkSelectField/LinkSelectField.test.js +16 -3
  15. package/lib/cjs/components/MultivaluesField/MultivaluesField.js +4 -4
  16. package/lib/cjs/components/MultivaluesField/MultivaluesField.test.js +10 -4
  17. package/lib/cjs/components/NumberField/NumberField.js +8 -2
  18. package/lib/cjs/components/NumberField/NumberField.test.js +14 -0
  19. package/lib/cjs/components/RadioGroupField/RadioGroupField.js +8 -2
  20. package/lib/cjs/components/RadioGroupField/RadioGroupField.test.js +14 -0
  21. package/lib/cjs/components/SelectField/SelectField.js +4 -1
  22. package/lib/cjs/components/SelectField/SelectField.test.js +20 -0
  23. package/lib/cjs/components/SelectFieldBase/SelectFieldBase.js +7 -2
  24. package/lib/cjs/components/SelectFieldBase/SelectFieldBase.test.js +17 -0
  25. package/lib/cjs/components/TextAreaField/TextAreaField.js +8 -2
  26. package/lib/cjs/components/TextAreaField/TextAreaField.test.js +20 -0
  27. package/lib/cjs/components/TextField/TextField.js +9 -2
  28. package/lib/cjs/components/TextField/TextField.test.js +20 -0
  29. package/lib/cjs/recipes/AttributeMappingReadOnlyField.stories.js +7 -1
  30. package/lib/components/CheckboxField/CheckboxField.js +6 -2
  31. package/lib/components/CheckboxField/CheckboxField.test.js +13 -0
  32. package/lib/components/ComboBoxField/ComboBoxField.js +5 -2
  33. package/lib/components/ComboBoxField/ComboBoxField.test.js +15 -0
  34. package/lib/components/EnvironmentBreadcrumb/EnvironmentBreadcrumb.js +16 -8
  35. package/lib/components/EnvironmentBreadcrumb/EnvironmentBreadcrumb.test.js +13 -0
  36. package/lib/components/FieldHelperText/FieldHelperText.js +8 -3
  37. package/lib/components/FileInputField/FileInputField.js +6 -2
  38. package/lib/components/FileInputField/FileInputField.test.js +13 -0
  39. package/lib/components/FileInputField/FileItem.js +5 -2
  40. package/lib/components/ImageUploadField/ImageUploadField.js +17 -6
  41. package/lib/components/ImageUploadField/ImageUploadFieldBase.js +3 -2
  42. package/lib/components/LinkSelectField/LinkSelectField.js +11 -3
  43. package/lib/components/LinkSelectField/LinkSelectField.test.js +14 -3
  44. package/lib/components/MultivaluesField/MultivaluesField.js +5 -5
  45. package/lib/components/MultivaluesField/MultivaluesField.test.js +8 -4
  46. package/lib/components/NumberField/NumberField.js +7 -2
  47. package/lib/components/NumberField/NumberField.test.js +12 -0
  48. package/lib/components/RadioGroupField/RadioGroupField.js +7 -2
  49. package/lib/components/RadioGroupField/RadioGroupField.test.js +12 -0
  50. package/lib/components/SelectField/SelectField.js +4 -1
  51. package/lib/components/SelectField/SelectField.test.js +15 -0
  52. package/lib/components/SelectFieldBase/SelectFieldBase.js +7 -2
  53. package/lib/components/SelectFieldBase/SelectFieldBase.test.js +13 -0
  54. package/lib/components/TextAreaField/TextAreaField.js +7 -2
  55. package/lib/components/TextAreaField/TextAreaField.test.js +15 -0
  56. package/lib/components/TextField/TextField.js +8 -2
  57. package/lib/components/TextField/TextField.test.js +15 -0
  58. package/lib/recipes/AttributeMappingReadOnlyField.stories.js +6 -1
  59. package/package.json +1 -1
  60. package/NOTICE.html +0 -4665
@@ -16,6 +16,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
16
16
 
17
17
  import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
18
18
  import PropTypes from 'prop-types';
19
+ import { VisuallyHidden } from '@react-aria/visually-hidden';
20
+ import { v4 as uuid } from 'uuid';
19
21
  import { Item, Menu } from '../../';
20
22
  import { ariaAttributesBasePropTypes } from '../../utils/devUtils/props/ariaAttributes';
21
23
  import ImagePreviewButton from './ImagePreviewButton';
@@ -40,6 +42,7 @@ var ImageUploadField = /*#__PURE__*/forwardRef(function (props, ref) {
40
42
  useImperativeHandle(ref, function () {
41
43
  return inputRef.current;
42
44
  });
45
+ var statusId = uuid();
43
46
  var onAction = useCallback(function (action) {
44
47
  // eslint-disable-next-line default-case
45
48
  switch (action) {
@@ -61,7 +64,7 @@ var ImageUploadField = /*#__PURE__*/forwardRef(function (props, ref) {
61
64
  }
62
65
  }
63
66
  }, [state.showFileDialog, props === null || props === void 0 ? void 0 : props.onRemove, state.removePreview]);
64
- return ___EmotionJSX(ImageUploadFieldBase, _extends({
67
+ return ___EmotionJSX(React.Fragment, null, ___EmotionJSX(ImageUploadFieldBase, _extends({
65
68
  fileName: state.fileName,
66
69
  handleInputChange: state.handleInputChange,
67
70
  handleLabelClick: state.handleLabelClick,
@@ -80,14 +83,22 @@ var ImageUploadField = /*#__PURE__*/forwardRef(function (props, ref) {
80
83
  previewHeight: props === null || props === void 0 ? void 0 : props.previewHeight,
81
84
  previewImage: state.previewImage,
82
85
  previewWidth: props === null || props === void 0 ? void 0 : props.previewWidth,
83
- widthHeightSx: state.widthHeightSx
86
+ widthHeightSx: state.widthHeightSx,
87
+ "aria-haspopup": state.isMenuOpen
84
88
  }), ___EmotionJSX(Menu, {
85
- onAction: onAction
89
+ onAction: onAction,
90
+ "aria-labelledby": statusId
86
91
  }, ___EmotionJSX(Item, {
87
- key: "upload"
92
+ key: "upload",
93
+ role: "button"
88
94
  }, uploadItemText), ___EmotionJSX(Item, {
89
- key: "remove"
90
- }, removeItemText)));
95
+ key: "remove",
96
+ role: "button"
97
+ }, removeItemText))), ___EmotionJSX(VisuallyHidden, {
98
+ "aria-live": "polite",
99
+ role: state.isMenuOpen ? 'button' : 'status',
100
+ id: statusId
101
+ }, state.isMenuOpen && 'Menu pop up expanded'));
91
102
  });
92
103
  ImageUploadField.propTypes = _objectSpread({
93
104
  /** Image preview (controlled), used to represent the current image state. */
@@ -16,8 +16,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
16
16
 
17
17
  import React, { forwardRef, useMemo, useRef } from 'react';
18
18
  import PropTypes from 'prop-types';
19
- import { useVisuallyHidden } from '@react-aria/visually-hidden';
20
19
  import omit from 'lodash/omit';
20
+ import { useVisuallyHidden } from '@react-aria/visually-hidden';
21
21
  import { PopoverMenu } from '../../index';
22
22
  import useField from '../../hooks/useField';
23
23
  import FieldHelperText from '../FieldHelperText';
@@ -55,7 +55,8 @@ var ImageUploadFieldBase = /*#__PURE__*/forwardRef(function (props, inputRef) {
55
55
  variant: "forms.input.wrapper"
56
56
  }, fieldContainerProps), ___EmotionJSX(Label, _extends({}, fieldLabelProps, {
57
57
  onClick: handleLabelClick,
58
- ref: labelRef
58
+ ref: labelRef,
59
+ tabIndex: "-1"
59
60
  })), ___EmotionJSX(PopoverMenu, {
60
61
  isOpen: isMenuOpen,
61
62
  onOpenChange: handleOpenMenuChange
@@ -17,6 +17,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
17
17
  import React, { forwardRef } from 'react';
18
18
  import PropTypes from 'prop-types';
19
19
  import MenuDown from 'mdi-react/MenuDownIcon';
20
+ import { v4 as uuid } from 'uuid';
21
+ import { VisuallyHidden } from '@react-aria/visually-hidden';
20
22
  import { Box, Button, Loader, Icon, Text } from '../../';
21
23
  import { ariaAttributesBasePropTypes, getAriaAttributeProps } from '../../utils/devUtils/props/ariaAttributes';
22
24
  import { usePropWarning, useSelectField } from '../../hooks';
@@ -34,11 +36,13 @@ import { jsx as ___EmotionJSX } from "@emotion/react";
34
36
  var LinkSelectField = /*#__PURE__*/forwardRef(function (props, ref) {
35
37
  var placeholder = props.placeholder,
36
38
  isDisabled = props.isDisabled,
37
- status = props.status;
39
+ status = props.status,
40
+ helperText = props.helperText;
38
41
 
39
42
  var _getAriaAttributeProp = getAriaAttributeProps(props),
40
43
  ariaProps = _getAriaAttributeProp.ariaProps;
41
44
 
45
+ var helperTextId = uuid();
42
46
  usePropWarning(props, 'disabled', 'isDisabled');
43
47
 
44
48
  var _useSelectField = useSelectField(_objectSpread(_objectSpread({
@@ -61,7 +65,8 @@ var LinkSelectField = /*#__PURE__*/forwardRef(function (props, ref) {
61
65
  className: fieldControlProps.className,
62
66
  ref: triggerRef,
63
67
  variant: "link",
64
- tabIndex: isDisabled ? -1 : 0
68
+ tabIndex: isDisabled ? -1 : 0,
69
+ "aria-describedby": helperText && helperTextId
65
70
  }, triggerProps, ariaProps), ___EmotionJSX(Text, {
66
71
  variant: "label",
67
72
  color: "active"
@@ -78,7 +83,10 @@ var LinkSelectField = /*#__PURE__*/forwardRef(function (props, ref) {
78
83
  sx: state.isOpen ? {
79
84
  transform: 'rotate(180deg)'
80
85
  } : null
81
- }))));
86
+ }))), ___EmotionJSX(VisuallyHidden, {
87
+ "aria-live": "polite",
88
+ id: helperTextId
89
+ }, helperText));
82
90
 
83
91
  return ___EmotionJSX(SelectFieldBase, _extends({}, props, selectFieldProps, {
84
92
  trigger: trigger
@@ -145,9 +145,9 @@ test('select field with helper text', function () {
145
145
  helperText: helperText,
146
146
  status: statuses.ERROR
147
147
  });
148
- var fieldHelperText = screen.getByText(helperText);
149
- expect(fieldHelperText).toBeInTheDocument();
150
- expect(fieldHelperText).toHaveClass("is-".concat(statuses.ERROR));
148
+ var fieldHelperText = screen.getAllByText(helperText);
149
+ expect(fieldHelperText[1]).toBeInTheDocument();
150
+ expect(fieldHelperText[1]).toHaveClass("is-".concat(statuses.ERROR));
151
151
  });
152
152
  test('displays a loader while loading', function () {
153
153
  var _getComponent = getComponent({
@@ -167,6 +167,17 @@ test('displays a loader while loading', function () {
167
167
  });
168
168
  expect(loader).not.toBeInTheDocument();
169
169
  });
170
+ test('passing helper text should display it and correct aria attributes on input', function () {
171
+ var testHelperText = 'testHelperText';
172
+ getComponent({
173
+ helperText: testHelperText,
174
+ status: statuses.ERROR
175
+ });
176
+ var helper = screen.getAllByText(testHelperText)[0];
177
+ expect(helper).toBeInTheDocument();
178
+ var helperTextID = helper.getAttribute('id');
179
+ expect(screen.getByRole('button')).toHaveAttribute('aria-describedby', helperTextID);
180
+ });
170
181
  test('should have no accessibility violations', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
171
182
  var _getComponent2, container, results;
172
183
 
@@ -30,7 +30,7 @@ import { useFilter } from '@react-aria/i18n';
30
30
  import { DismissButton, useOverlayPosition } from '@react-aria/overlays';
31
31
  import { useLayoutEffect, useResizeObserver } from '@react-aria/utils';
32
32
  import { useListState } from '@react-stately/list';
33
- import { Box, FieldHelperText, Chip, Icon, IconButton, PopoverContainer, ScrollBox, Text, TextField } from '../../';
33
+ import { Box, Chip, Icon, IconButton, PopoverContainer, ScrollBox, Text, TextField } from '../../';
34
34
  import { ariaAttributesBasePropTypes, getAriaAttributeProps } from '../../utils/devUtils/props/ariaAttributes';
35
35
  import { usePropWarning } from '../../hooks';
36
36
  import ListBox from '../ListBox';
@@ -429,10 +429,10 @@ var MultivaluesField = /*#__PURE__*/forwardRef(function (props, ref) {
429
429
  slots: {
430
430
  beforeInput: ___EmotionJSX(React.Fragment, null, readOnlyItems, " ", selectedItems, readOnlyInputEntry)
431
431
  },
432
- value: filterString
433
- }, ariaProps, inputProps)), helperText && ___EmotionJSX(FieldHelperText, {
434
- status: status
435
- }, helperText), ___EmotionJSX(PopoverContainer, {
432
+ value: filterString,
433
+ helperText: helperText,
434
+ "aria-invalid": status === 'error' && true
435
+ }, ariaProps, inputProps)), ___EmotionJSX(PopoverContainer, {
436
436
  hasNoArrow: true,
437
437
  isDismissable: true,
438
438
  isNonModal: true,
@@ -388,15 +388,19 @@ test('read only keys', function () {
388
388
  var deleteButton2 = firstChip.nextSibling;
389
389
  expect(deleteButton2).toBeNull();
390
390
  });
391
- test(' multivalue field with helper text', function () {
392
- var helperText = 'helper text';
391
+ test('passing helper text should display it and correct aria attributes on input', function () {
392
+ var testHelperText = 'testHelperText';
393
393
  getComponent({
394
- helperText: helperText,
394
+ helperText: testHelperText,
395
395
  status: statuses.ERROR
396
396
  });
397
- var helper = screen.getByText(helperText);
397
+ var helper = screen.getByText(testHelperText);
398
398
  expect(helper).toBeInTheDocument();
399
399
  expect(helper).toHaveClass("is-".concat(statuses.ERROR));
400
+ var input = screen.getByRole('combobox');
401
+ expect(input).toHaveAttribute('aria-invalid', 'true');
402
+ var helperTextID = helper.getAttribute('id');
403
+ expect(input).toHaveAttribute('aria-describedby', helperTextID);
400
404
  });
401
405
  test('read only field', function () {
402
406
  var isReadOnly = true;
@@ -24,6 +24,7 @@ import { useNumberFieldState } from '@react-stately/numberfield';
24
24
  import { useLocale } from '@react-aria/i18n';
25
25
  import { mergeProps } from '@react-aria/utils';
26
26
  import omit from 'lodash/omit';
27
+ import { v4 as uuid } from 'uuid';
27
28
  import { Box, FieldHelperText, Icon, IconButton, Input, Label } from '../../';
28
29
  import { ariaAttributesBasePropTypes } from '../../utils/devUtils/props/ariaAttributes';
29
30
  import { useField, usePropWarning } from '../../hooks';
@@ -135,6 +136,7 @@ var NumberField = /*#__PURE__*/forwardRef(function (props, ref) {
135
136
  };
136
137
 
137
138
  inputProps['aria-roledescription'] = null;
139
+ var helperTextId = uuid();
138
140
  return ___EmotionJSX(Box, fieldContainerProps, ___EmotionJSX(Label, mergeProps(fieldLabelProps, labelProps)), ___EmotionJSX(Box, _extends({
139
141
  variant: "numberField.noDefaultArrows"
140
142
  }, groupProps), ___EmotionJSX(Box, {
@@ -146,9 +148,12 @@ var NumberField = /*#__PURE__*/forwardRef(function (props, ref) {
146
148
  // overwrite them like defaultValue, value, ect.
147
149
 
148
150
  }, updatedFieldControlProps, omit(inputProps, ['name', 'onFocus', 'onBlur']), {
149
- onChange: onInputChange
151
+ onChange: onInputChange,
152
+ "aria-describedby": helperText && helperTextId,
153
+ role: "textbox"
150
154
  })), ControlArrows), helperText && ___EmotionJSX(FieldHelperText, {
151
- status: status
155
+ status: status,
156
+ id: helperTextId
152
157
  }, helperText)));
153
158
  });
154
159
  export default NumberField;
@@ -140,4 +140,16 @@ test('number field can be focused', function () {
140
140
  getComponent();
141
141
  userEvent.tab();
142
142
  expect(screen.getByLabelText(testLabel)).toHaveClass('is-focused');
143
+ });
144
+ test('passing helper text should display it and correct aria attributes on input', function () {
145
+ var testHelperText = 'testHelperText';
146
+ getComponent({
147
+ helperText: testHelperText,
148
+ status: statuses.ERROR
149
+ });
150
+ var helper = screen.getByText(testHelperText);
151
+ expect(helper).toBeInTheDocument();
152
+ expect(helper).toHaveClass("is-".concat(statuses.ERROR));
153
+ var helperTextID = helper.getAttribute('id');
154
+ expect(screen.getByRole('textbox')).toHaveAttribute('aria-describedby', helperTextID);
143
155
  });
@@ -18,6 +18,7 @@ import React, { forwardRef } from 'react';
18
18
  import { useRadioGroup } from '@react-aria/radio';
19
19
  import { useRadioGroupState } from '@react-stately/radio';
20
20
  import PropTypes from 'prop-types';
21
+ import { v4 as uuid } from 'uuid';
21
22
  import { Box, FieldHelperText, Label } from '../../';
22
23
  import { ariaAttributesBasePropTypes } from '../../utils/devUtils/props/ariaAttributes';
23
24
  import { useStatusClasses, usePropWarning } from '../../hooks';
@@ -59,6 +60,7 @@ var RadioGroupField = /*#__PURE__*/forwardRef(function (props, ref) {
59
60
  var unhandledAriaProps = {
60
61
  'aria-controls': props['aria-controls']
61
62
  };
63
+ var helperTextId = uuid();
62
64
  return ___EmotionJSX(Box, _extends({
63
65
  ref: ref,
64
66
  className: classNames
@@ -69,7 +71,9 @@ var RadioGroupField = /*#__PURE__*/forwardRef(function (props, ref) {
69
71
  variant: "forms.label.radioGroup"
70
72
  }, labelProps), label), ___EmotionJSX(Box, {
71
73
  variant: "forms.radioGroupWrapper",
72
- isRow: orientation === ORIENTATION.HORIZONTAL
74
+ isRow: orientation === ORIENTATION.HORIZONTAL,
75
+ "aria-labelledby": helperText && helperTextId,
76
+ "data-testid": "radioGroupWrapper"
73
77
  }, ___EmotionJSX(RadioContext.Provider, {
74
78
  value: _objectSpread({
75
79
  isDisabled: isDisabled
@@ -78,7 +82,8 @@ var RadioGroupField = /*#__PURE__*/forwardRef(function (props, ref) {
78
82
  status: status,
79
83
  sx: {
80
84
  pt: 'xs'
81
- }
85
+ },
86
+ id: helperTextId
82
87
  }, helperText));
83
88
  });
84
89
  RadioGroupField.propTypes = _objectSpread({
@@ -156,4 +156,16 @@ test('radio group with horizontal orientation', function () {
156
156
  });
157
157
  var group = screen.getByRole('radiogroup');
158
158
  expect(group).toHaveAttribute('aria-orientation', ORIENTATION.HORIZONTAL);
159
+ });
160
+ test('passing helper text should display it and correct aria attributes on input', function () {
161
+ var testHelperText = 'testHelperText';
162
+ getComponent({
163
+ helperText: testHelperText,
164
+ status: statuses.ERROR
165
+ });
166
+ var helper = screen.getByText(testHelperText);
167
+ expect(helper).toBeInTheDocument();
168
+ expect(helper).toHaveClass("is-".concat(statuses.ERROR));
169
+ var helperTextID = helper.getAttribute('id');
170
+ expect(screen.getByTestId('radioGroupWrapper')).toHaveAttribute('aria-labelledby', helperTextID);
159
171
  });
@@ -30,12 +30,15 @@ import statuses from '../../utils/devUtils/constants/statuses';
30
30
 
31
31
  import { jsx as ___EmotionJSX } from "@emotion/react";
32
32
  var SelectField = /*#__PURE__*/forwardRef(function (props, ref) {
33
+ var status = props.status;
33
34
  usePropWarning(props, 'disabled', 'isDisabled');
34
35
 
35
36
  var _useSelectField = useSelectField(props, ref),
36
37
  selectFieldProps = _extends({}, _useSelectField);
37
38
 
38
- return ___EmotionJSX(SelectFieldBase, _extends({}, props, selectFieldProps));
39
+ return ___EmotionJSX(SelectFieldBase, _extends({}, props, selectFieldProps, {
40
+ "aria-invalid": status === 'error' && true
41
+ }));
39
42
  });
40
43
  SelectField.propTypes = _objectSpread({
41
44
  /** Alignment of the popover menu relative to the trigger. */
@@ -3,6 +3,7 @@ import React from 'react';
3
3
  import axeTest from '../../utils/testUtils/testAxe';
4
4
  import { render, screen } from '../../utils/testUtils/testWrapper';
5
5
  import { SelectField, Item } from '../../index';
6
+ import statuses from '../../utils/devUtils/constants/statuses';
6
7
  import { jsx as ___EmotionJSX } from "@emotion/react";
7
8
  var items = [{
8
9
  name: 'a'
@@ -67,4 +68,18 @@ test('default select field', function () {
67
68
  expect(hiddenLabel.closest('[aria-hidden="true"]')).not.toBeNull();
68
69
  expect(visibleLabel.closest('[aria-hidden="true"]')).toBeNull();
69
70
  /* eslint-enable testing-library/no-node-access */
71
+ });
72
+ test('passing helper text should display it and correct aria attributes on input', function () {
73
+ var testHelperText = 'testHelperText';
74
+ getComponent({
75
+ helperText: testHelperText,
76
+ status: statuses.ERROR
77
+ });
78
+ var helper = screen.getByText(testHelperText);
79
+ expect(helper).toBeInTheDocument();
80
+ expect(helper).toHaveClass("is-".concat(statuses.ERROR));
81
+ var visibleInput = screen.getAllByLabelText(defaultProps.label)[1];
82
+ expect(visibleInput).toHaveAttribute('aria-invalid', 'true');
83
+ var helperTextID = helper.getAttribute('id');
84
+ expect(screen.getByRole('button')).toHaveAttribute('aria-describedby', helperTextID);
70
85
  });
@@ -20,6 +20,7 @@ import React, { forwardRef } from 'react';
20
20
  import PropTypes from 'prop-types';
21
21
  import { HiddenSelect } from '@react-aria/select';
22
22
  import MenuDown from 'mdi-react/MenuDownIcon';
23
+ import { v4 as uuid } from 'uuid';
23
24
  import { ariaAttributesBasePropTypes, getAriaAttributeProps } from '../../utils/devUtils/props/ariaAttributes';
24
25
  import statuses from '../../utils/devUtils/constants/statuses';
25
26
  import Box from '../Box';
@@ -64,13 +65,16 @@ var SelectFieldBase = /*#__PURE__*/forwardRef(function (_ref, ref) {
64
65
  var _getAriaAttributeProp = getAriaAttributeProps(others),
65
66
  ariaProps = _getAriaAttributeProp.ariaProps;
66
67
 
68
+ var helperTextId = uuid();
69
+
67
70
  var defaultTrigger = ___EmotionJSX(Box, {
68
71
  className: fieldControlProps.className,
69
72
  variant: "forms.input.container"
70
73
  }, ___EmotionJSX(Button, _extends({
71
74
  className: fieldControlProps.className,
72
75
  ref: triggerRef,
73
- variant: "forms.select"
76
+ variant: "forms.select",
77
+ "aria-describedby": helperText && helperTextId
74
78
  }, triggerProps, ariaProps), ___EmotionJSX(Box, _extends({
75
79
  as: "span",
76
80
  variant: "forms.select.currentValue"
@@ -101,7 +105,8 @@ var SelectFieldBase = /*#__PURE__*/forwardRef(function (_ref, ref) {
101
105
  name: name,
102
106
  isDisabled: true
103
107
  }), trigger || defaultTrigger, overlay, helperText && ___EmotionJSX(FieldHelperText, {
104
- status: status
108
+ status: status,
109
+ id: helperTextId
105
110
  }, helperText));
106
111
  });
107
112
  SelectFieldBase.propTypes = _objectSpread({
@@ -369,6 +369,19 @@ test('form wrapper will have a max label column width when custom width set', fu
369
369
  var textAreaContainer = screen.getByTestId(testId);
370
370
  expect(textAreaContainer).toHaveStyle('grid-template-columns: 120px auto');
371
371
  });
372
+ test('passing helper text should display it and correct aria attributes on input', function () {
373
+ var testHelperText = 'testHelperText';
374
+ getComponent({
375
+ helperText: testHelperText,
376
+ status: statuses.ERROR
377
+ });
378
+ var helper = screen.getByText(testHelperText);
379
+ expect(helper).toBeInTheDocument();
380
+ expect(helper).toHaveClass("is-".concat(statuses.ERROR));
381
+ var visibleInput = screen.getAllByLabelText(defaultProps.label)[1];
382
+ var helperTextID = helper.getAttribute('id');
383
+ expect(visibleInput).toHaveAttribute('aria-describedby', helperTextID);
384
+ });
372
385
  test('should have no accessibility violations', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
373
386
  var _getComponent3, container, results;
374
387
 
@@ -17,6 +17,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
17
17
  import React, { forwardRef, useRef, useImperativeHandle, useEffect, useCallback } from 'react';
18
18
  import PropTypes from 'prop-types';
19
19
  import { useLayoutEffect, useResizeObserver } from '@react-aria/utils';
20
+ import { v4 as uuid } from 'uuid';
20
21
  import { Box, FieldHelperText, Label, TextArea } from '../../';
21
22
  import { ariaAttributesBasePropTypes } from '../../utils/devUtils/props/ariaAttributes';
22
23
  import { useColumnStyles, useField, useLabelHeight, usePropWarning } from '../../hooks';
@@ -49,6 +50,7 @@ var TextAreaField = /*#__PURE__*/forwardRef(function (props, ref) {
49
50
  var labelWrapperRef = useRef();
50
51
  var slotContainer = useRef();
51
52
  var textAreaRef = useRef();
53
+ var helperTextId = uuid();
52
54
  usePropWarning(props, 'disabled', 'isDisabled');
53
55
  /* istanbul ignore next */
54
56
 
@@ -136,12 +138,15 @@ var TextAreaField = /*#__PURE__*/forwardRef(function (props, ref) {
136
138
  paddingRight: '35px'
137
139
  } : {
138
140
  overflow: 'hidden'
139
- }
141
+ },
142
+ "aria-invalid": status === 'error' && true,
143
+ "aria-describedby": helperText && helperTextId
140
144
  })), (slots === null || slots === void 0 ? void 0 : slots.inContainer) && ___EmotionJSX(Box, {
141
145
  variant: "boxes.textFieldInContainerSlot",
142
146
  ref: slotContainer
143
147
  }, slots === null || slots === void 0 ? void 0 : slots.inContainer)), helperText && ___EmotionJSX(FieldHelperText, {
144
- status: status
148
+ status: status,
149
+ id: helperTextId
145
150
  }, helperText));
146
151
  });
147
152
  TextAreaField.propTypes = _objectSpread({
@@ -7,6 +7,7 @@ import userEvent from '@testing-library/user-event';
7
7
  import { fireEvent } from '@testing-library/react';
8
8
  import axeTest from '../../utils/testUtils/testAxe';
9
9
  import { screen, render } from '../../utils/testUtils/testWrapper';
10
+ import statuses from '../../utils/devUtils/constants/statuses';
10
11
  import TextAreaField from '.';
11
12
  import { jsx as ___EmotionJSX } from "@emotion/react";
12
13
  var testId = 'test-textAreaField';
@@ -133,4 +134,18 @@ test('providing slot props causes slot to render', function () {
133
134
  slots: slots
134
135
  });
135
136
  expect(screen.getByTestId('testSlot')).toBeInTheDocument();
137
+ });
138
+ test('passing helper text should display it and correct aria attributes on input', function () {
139
+ var testHelperText = 'testHelperText';
140
+ getComponent({
141
+ helperText: testHelperText,
142
+ status: statuses.ERROR
143
+ });
144
+ var helper = screen.getByText(testHelperText);
145
+ expect(helper).toBeInTheDocument();
146
+ expect(helper).toHaveClass("is-".concat(statuses.ERROR));
147
+ var input = screen.getByRole('textbox');
148
+ expect(input).toHaveAttribute('aria-invalid', 'true');
149
+ var helperTextID = helper.getAttribute('id');
150
+ expect(input).toHaveAttribute('aria-describedby', helperTextID);
136
151
  });
@@ -16,6 +16,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
16
16
 
17
17
  import React, { forwardRef, useRef, useImperativeHandle } from 'react';
18
18
  import PropTypes from 'prop-types';
19
+ import { v4 as uuid } from 'uuid';
19
20
  import { Box, FieldHelperText, Input, Label } from '../../';
20
21
  import { ariaAttributesBasePropTypes } from '../../utils/devUtils/props/ariaAttributes';
21
22
  import { useField, useLabelHeight, usePropWarning } from '../../hooks';
@@ -55,6 +56,7 @@ var TextField = /*#__PURE__*/forwardRef(function (props, ref) {
55
56
  var columnStyleProps = useColumnStyles({
56
57
  labelMode: props.labelMode
57
58
  });
59
+ var helperTextId = uuid();
58
60
  return ___EmotionJSX(Box, _extends({
59
61
  variant: "forms.input.wrapper"
60
62
  }, fieldContainerProps, {
@@ -69,8 +71,12 @@ var TextField = /*#__PURE__*/forwardRef(function (props, ref) {
69
71
  className: fieldControlProps.className
70
72
  }, wrapperProps), slots === null || slots === void 0 ? void 0 : slots.beforeInput, ___EmotionJSX(Input, _extends({
71
73
  ref: inputRef
72
- }, fieldControlProps)), slots === null || slots === void 0 ? void 0 : slots.inContainer), helperText && ___EmotionJSX(FieldHelperText, {
73
- status: status
74
+ }, fieldControlProps, {
75
+ "aria-invalid": status === 'error' && true,
76
+ "aria-describedby": helperText && helperTextId
77
+ })), slots === null || slots === void 0 ? void 0 : slots.inContainer), helperText && ___EmotionJSX(FieldHelperText, {
78
+ status: status,
79
+ id: helperTextId
74
80
  }, helperText));
75
81
  });
76
82
  TextField.propTypes = _objectSpread({
@@ -7,6 +7,7 @@ import { render, screen } from '@testing-library/react';
7
7
  import userEvent from '@testing-library/user-event';
8
8
  import TextField from '.';
9
9
  import axeTest from '../../utils/testUtils/testAxe';
10
+ import statuses from '../../utils/devUtils/constants/statuses';
10
11
  import { jsx as ___EmotionJSX } from "@emotion/react";
11
12
  var testId = 'test-text-field';
12
13
  var testLabel = 'Test Label';
@@ -134,4 +135,18 @@ test('text field container and input have is-read-only class name when isReadOnl
134
135
  });
135
136
  var control = screen.getByLabelText(testLabel);
136
137
  expect(control).toHaveClass('is-read-only');
138
+ });
139
+ test('passing helper text should display it and correct aria attributes on input', function () {
140
+ var testHelperText = 'testHelperText';
141
+ getComponent({
142
+ helperText: testHelperText,
143
+ status: statuses.ERROR
144
+ });
145
+ var helper = screen.getByText(testHelperText);
146
+ expect(helper).toBeInTheDocument();
147
+ expect(helper).toHaveClass("is-".concat(statuses.ERROR));
148
+ var input = screen.getByRole('textbox');
149
+ expect(input).toHaveAttribute('aria-invalid', 'true');
150
+ var helperTextID = helper.getAttribute('id');
151
+ expect(input).toHaveAttribute('aria-describedby', helperTextID);
137
152
  });
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import CreateIcon from 'mdi-react/CreateIcon';
3
3
  import AlertCircleIcon from 'mdi-react/AlertCircleIcon';
4
+ import { v4 as uuid } from 'uuid';
4
5
  import { Box, Chip, IconButton, Text, Icon, Separator, TextField, HelpHint } from '../index';
5
6
  import { jsx as ___EmotionJSX } from "@emotion/react";
6
7
  export default {
@@ -69,6 +70,7 @@ var sx = {
69
70
  width: 'md'
70
71
  }
71
72
  };
73
+ var helperTextId = uuid();
72
74
 
73
75
  var Row = function Row(props) {
74
76
  var withChip = props.withChip,
@@ -92,6 +94,7 @@ var Row = function Row(props) {
92
94
  width: '165px'
93
95
  }
94
96
  },
97
+ "aria-labelledby": withError && helperTextId,
95
98
  slots: withError && {
96
99
  inContainer: ___EmotionJSX(Icon, {
97
100
  icon: AlertCircleIcon,
@@ -200,7 +203,9 @@ export var WithError = function WithError() {
200
203
  icon: AlertCircleIcon,
201
204
  color: "#A31300"
202
205
  }), ___EmotionJSX(Text, {
203
- sx: withErrorSx.text
206
+ sx: withErrorSx.text,
207
+ id: helperTextId,
208
+ role: "alert"
204
209
  }, "This attribute is unavailable. Please map the attribute again or re-map to a different attribute.")), ___EmotionJSX(Box, {
205
210
  sx: sx.defaultFieldsWrapperBox
206
211
  }, ___EmotionJSX(Box, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pingux/astro",
3
- "version": "1.36.1",
3
+ "version": "1.36.2-alpha.1",
4
4
  "description": "PingUX themeable React component library",
5
5
  "repository": {
6
6
  "type": "git",