@openedx/paragon 22.13.0 → 22.15.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 (258) hide show
  1. package/dist/Alert/_variables.scss +2 -1
  2. package/dist/Annotation/index.js.map +1 -1
  3. package/dist/Annotation/index.scss +6 -5
  4. package/dist/Avatar/index.js.map +1 -1
  5. package/dist/AvatarButton/index.js.map +1 -1
  6. package/dist/Breadcrumb/index.js.map +1 -1
  7. package/dist/Bubble/index.js +1 -0
  8. package/dist/Bubble/index.js.map +1 -1
  9. package/dist/Bubble/index.scss +3 -2
  10. package/dist/Button/deprecated/index.js.map +1 -1
  11. package/dist/Button/index.scss +19 -18
  12. package/dist/Card/CardCarousel/CardCarouselHeader.js +2 -2
  13. package/dist/Card/CardCarousel/CardCarouselHeader.js.map +1 -1
  14. package/dist/Card/CardFooter.js.map +1 -1
  15. package/dist/Card/CardHeader.js +1 -1
  16. package/dist/Card/CardHeader.js.map +1 -1
  17. package/dist/Card/CardImageCap.js.map +1 -1
  18. package/dist/Card/CardStatus.js.map +1 -1
  19. package/dist/Card/_variables.scss +3 -2
  20. package/dist/Card/index.js.map +1 -1
  21. package/dist/Card/index.scss +10 -9
  22. package/dist/Chip/ChipIcon.d.ts +1 -1
  23. package/dist/Chip/index.js +1 -0
  24. package/dist/Chip/index.js.map +1 -1
  25. package/dist/ChipCarousel/index.js.map +1 -1
  26. package/dist/Collapsible/index.js.map +1 -1
  27. package/dist/ColorPicker/index.js +1 -1
  28. package/dist/ColorPicker/index.js.map +1 -1
  29. package/dist/ColorPicker/index.scss +2 -1
  30. package/dist/DataTable/CollapsibleButtonGroup.js +2 -2
  31. package/dist/DataTable/CollapsibleButtonGroup.js.map +1 -1
  32. package/dist/DataTable/DropdownFilters.js +1 -1
  33. package/dist/DataTable/DropdownFilters.js.map +1 -1
  34. package/dist/DataTable/TableRow.js.map +1 -1
  35. package/dist/DataTable/filters/CheckboxFilter.js.map +1 -1
  36. package/dist/DataTable/filters/DropdownFilter.js.map +1 -1
  37. package/dist/DataTable/filters/MultiSelectDropdownFilter.js.map +1 -1
  38. package/dist/DataTable/filters/TextFilter.js.map +1 -1
  39. package/dist/DataTable/index.scss +14 -13
  40. package/dist/DataTable/utils/getVisibleColumns.js +1 -1
  41. package/dist/DataTable/utils/getVisibleColumns.js.map +1 -1
  42. package/dist/Dropdown/_variables.scss +2 -1
  43. package/dist/Dropdown/deprecated/DropdownMenu.js +15 -19
  44. package/dist/Dropdown/deprecated/DropdownMenu.js.map +1 -1
  45. package/dist/Dropdown/deprecated/index.js +1 -1
  46. package/dist/Dropdown/deprecated/index.js.map +1 -1
  47. package/dist/Dropdown/index.js.map +1 -1
  48. package/dist/Dropzone/DefaultContent.js.map +1 -1
  49. package/dist/Dropzone/UploadProgress.js.map +1 -1
  50. package/dist/Dropzone/index.scss +3 -2
  51. package/dist/Fieldset/index.js.map +1 -1
  52. package/dist/Form/FormAutosuggest.js +1 -1
  53. package/dist/Form/FormAutosuggest.js.map +1 -1
  54. package/dist/Form/FormControl.js.map +1 -1
  55. package/dist/Form/FormControlDecorator.js.map +1 -1
  56. package/dist/Form/FormGroupContext.d.ts +1 -1
  57. package/dist/Form/FormGroupContext.js.map +1 -1
  58. package/dist/Form/FormText.js.map +1 -1
  59. package/dist/Form/_index.scss +9 -7
  60. package/dist/Form/_variables.scss +4 -2
  61. package/dist/Form/fieldUtils.js.map +1 -1
  62. package/dist/Hyperlink/index.d.ts +10 -5
  63. package/dist/Hyperlink/index.js +57 -25
  64. package/dist/Hyperlink/index.js.map +1 -1
  65. package/dist/Hyperlink/index.scss +3 -1
  66. package/dist/Icon/index.js.map +1 -1
  67. package/dist/IconButton/index.d.ts +13 -8
  68. package/dist/IconButton/index.js.map +1 -1
  69. package/dist/IconButtonToggle/index.js.map +1 -1
  70. package/dist/IconButtonToggle/index.scss +3 -1
  71. package/dist/Input/index.js.map +1 -1
  72. package/dist/InputSelect/index.js.map +1 -1
  73. package/dist/Layout/index.js.map +1 -1
  74. package/dist/ListBox/index.js.map +1 -1
  75. package/dist/ListBoxOption/index.js.map +1 -1
  76. package/dist/Menu/SelectMenu.js +1 -1
  77. package/dist/Menu/SelectMenu.js.map +1 -1
  78. package/dist/Menu/index.js +1 -1
  79. package/dist/Menu/index.js.map +1 -1
  80. package/dist/Modal/ModalContext.d.ts +1 -1
  81. package/dist/Modal/ModalDialog.d.ts +1 -1
  82. package/dist/Modal/ModalDialog.js.map +1 -1
  83. package/dist/Modal/ModalDialogBody.js +1 -1
  84. package/dist/Modal/ModalDialogBody.js.map +1 -1
  85. package/dist/Modal/ModalDialogHeroBackground.js.map +1 -1
  86. package/dist/Modal/ModalLayer.d.ts +3 -3
  87. package/dist/Modal/ModalLayer.js.map +1 -1
  88. package/dist/Modal/ModalPopup.js.map +1 -1
  89. package/dist/Modal/_ModalDialog.scss +3 -1
  90. package/dist/Modal/index.js +3 -1
  91. package/dist/Modal/index.js.map +1 -1
  92. package/dist/Modal/index.scss +3 -5
  93. package/dist/Nav/_mixins.scss +3 -1
  94. package/dist/Overlay/index.d.ts +2 -2
  95. package/dist/PageBanner/index.js.map +1 -1
  96. package/dist/PageBanner/index.scss +2 -1
  97. package/dist/Pagination/PaginationContext.js.map +1 -1
  98. package/dist/Pagination/index.js.map +1 -1
  99. package/dist/Popover/_variables.scss +2 -1
  100. package/dist/Popover/index.js.map +1 -1
  101. package/dist/ProductTour/Checkpoint.scss +9 -8
  102. package/dist/ProductTour/index.js +1 -1
  103. package/dist/ProductTour/index.js.map +1 -1
  104. package/dist/ProgressBar/index.js.map +1 -1
  105. package/dist/Scrollable/index.js +1 -1
  106. package/dist/Scrollable/index.js.map +1 -1
  107. package/dist/SearchField/SearchFieldAdvanced.js.map +1 -1
  108. package/dist/SearchField/index.scss +2 -1
  109. package/dist/SelectableBox/SelectableBoxSet.js.map +1 -1
  110. package/dist/Sheet/index.js.map +1 -1
  111. package/dist/Stack/index.js.map +1 -1
  112. package/dist/StatefulButton/index.js.map +1 -1
  113. package/dist/StatusAlert/index.js.map +1 -1
  114. package/dist/Stepper/StepperHeader.js +1 -1
  115. package/dist/Stepper/StepperHeader.js.map +1 -1
  116. package/dist/Stepper/StepperHeaderStep.js.map +1 -1
  117. package/dist/Sticky/index.js.map +1 -1
  118. package/dist/Table/_variables.scss +2 -1
  119. package/dist/Tabs/deprecated/index.js.map +1 -1
  120. package/dist/Tabs/index.js +1 -1
  121. package/dist/Tabs/index.js.map +1 -1
  122. package/dist/Toast/ToastContainer.scss +1 -1
  123. package/dist/Toast/index.scss +2 -2
  124. package/dist/Truncate/index.js +1 -1
  125. package/dist/Truncate/index.js.map +1 -1
  126. package/dist/ValidationFormGroup/index.js.map +1 -1
  127. package/dist/asInput/index.js.map +1 -1
  128. package/dist/hooks/{useArrowKeyNavigation.js → useArrowKeyNavigationHook.js} +5 -1
  129. package/dist/hooks/useArrowKeyNavigationHook.js.map +1 -0
  130. package/dist/hooks/{useIndexOfLastVisibleChild.js → useIndexOfLastVisibleChildHook.js} +5 -1
  131. package/dist/hooks/useIndexOfLastVisibleChildHook.js.map +1 -0
  132. package/dist/hooks/{useIsVisible.js → useIsVisibleHook.js} +1 -1
  133. package/dist/hooks/useIsVisibleHook.js.map +1 -0
  134. package/dist/hooks/{useToggle.js → useToggleHook.js} +5 -1
  135. package/dist/hooks/useToggleHook.js.map +1 -0
  136. package/dist/hooks/{useWindowSize.js → useWindowSizeHook.js} +1 -1
  137. package/dist/hooks/useWindowSizeHook.js.map +1 -0
  138. package/dist/index.d.ts +6 -6
  139. package/dist/index.js +6 -6
  140. package/dist/paragon.css +1 -45
  141. package/dist/utils/newId.js.map +1 -1
  142. package/dist/withDeprecatedProps.js.map +1 -1
  143. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/CHANGELOG.md +50 -0
  144. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/LICENSE +7 -0
  145. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/README.md +37 -0
  146. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/dist/index.d.ts +20 -0
  147. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/dist/index.js +79 -0
  148. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/dist/index.js.map +1 -0
  149. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/package.json +40 -0
  150. package/icons/node_modules/@svgr/babel-plugin-add-jsx-attribute/tsconfig.json +4 -0
  151. package/icons/package.json +1 -1
  152. package/package.json +12 -19
  153. package/scss/core/_exports.module.scss +7 -6
  154. package/scss/core/_functions.scss +9 -7
  155. package/scss/core/_typography.scss +2 -1
  156. package/scss/core/_utilities.scss +2 -1
  157. package/scss/core/_variables.scss +98 -95
  158. package/src/Alert/_variables.scss +2 -1
  159. package/src/Annotation/index.scss +6 -5
  160. package/src/Breadcrumb/Breadcrumb.test.jsx +3 -2
  161. package/src/Bubble/index.scss +3 -2
  162. package/src/Bubble/index.tsx +1 -0
  163. package/src/Button/Button.test.tsx +6 -1
  164. package/src/Button/deprecated/Button.test.jsx +6 -4
  165. package/src/Button/index.scss +19 -18
  166. package/src/Card/CardCarousel/tests/CardCarouselControls.test.jsx +6 -4
  167. package/src/Card/_variables.scss +3 -2
  168. package/src/Card/index.scss +10 -9
  169. package/src/Chip/index.tsx +1 -0
  170. package/src/Collapsible/Collapsible.test.jsx +15 -7
  171. package/src/ColorPicker/ColorPicker.test.jsx +9 -16
  172. package/src/ColorPicker/index.jsx +1 -1
  173. package/src/ColorPicker/index.scss +2 -1
  174. package/src/DataTable/CollapsibleButtonGroup.jsx +2 -2
  175. package/src/DataTable/DropdownFilters.jsx +1 -1
  176. package/src/DataTable/dataviews.mdx +1 -8
  177. package/src/DataTable/index.scss +14 -13
  178. package/src/DataTable/selection/tests/ControlledSelectHeader.test.jsx +6 -4
  179. package/src/DataTable/tests/BulkActions.test.jsx +2 -4
  180. package/src/DataTable/tests/DataViewToggle.test.jsx +3 -7
  181. package/src/DataTable/tests/DropdownFilters.test.jsx +1 -1
  182. package/src/DataTable/tests/TableActions.test.jsx +1 -1
  183. package/src/Dropdown/_variables.scss +2 -1
  184. package/src/Dropdown/deprecated/Dropdown.test.jsx +43 -27
  185. package/src/Dropzone/README.md +3 -3
  186. package/src/Dropzone/index.scss +3 -2
  187. package/src/Dropzone/tests/__snapshots__/Dropzone.test.jsx.snap +10 -1
  188. package/src/Form/FormAutosuggest.jsx +1 -1
  189. package/src/Form/FormGroupContext.tsx +1 -1
  190. package/src/Form/_index.scss +9 -7
  191. package/src/Form/_variables.scss +4 -2
  192. package/src/Form/tests/FormAutosuggest.test.jsx +76 -57
  193. package/src/Form/tests/FormCheckboxSet.test.jsx +3 -2
  194. package/src/Form/tests/FormControl.test.jsx +9 -6
  195. package/src/Form/tests/FormRadioSet.test.jsx +3 -2
  196. package/src/Hyperlink/Hyperlink.test.tsx +50 -20
  197. package/src/Hyperlink/README.md +14 -1
  198. package/src/Hyperlink/index.scss +3 -1
  199. package/src/Hyperlink/index.tsx +71 -30
  200. package/src/IconButtonToggle/IconButtonToggle.test.jsx +3 -2
  201. package/src/IconButtonToggle/index.scss +3 -1
  202. package/src/ListBox/ListBox.test.jsx +8 -4
  203. package/src/MailtoLink/MailtoLink.test.jsx +12 -3
  204. package/src/Menu/Menu.test.jsx +27 -19
  205. package/src/Menu/SelectMenu.jsx +1 -1
  206. package/src/Menu/SelectMenu.test.jsx +35 -16
  207. package/src/Menu/__snapshots__/Menu.test.jsx.snap +0 -1
  208. package/src/Menu/index.jsx +1 -1
  209. package/src/Modal/ModalDialogBody.jsx +1 -1
  210. package/src/Modal/_ModalDialog.scss +3 -1
  211. package/src/Modal/index.jsx +2 -0
  212. package/src/Modal/index.scss +3 -5
  213. package/src/Modal/tests/ModalLayer.test.tsx +3 -2
  214. package/src/Nav/_mixins.scss +3 -1
  215. package/src/OverflowScroll/data/tests/useOverflowScroll.test.jsx +1 -2
  216. package/src/OverflowScroll/data/tests/useOverflowScrollActions.test.jsx +1 -1
  217. package/src/OverflowScroll/data/tests/useOverflowScrollElementAttributes.test.jsx +1 -1
  218. package/src/OverflowScroll/data/tests/useOverflowScrollEventListeners.test.jsx +1 -2
  219. package/src/PageBanner/index.scss +2 -1
  220. package/src/Pagination/Pagination.test.jsx +36 -28
  221. package/src/Popover/_variables.scss +2 -1
  222. package/src/ProductTour/Checkpoint.scss +9 -8
  223. package/src/ProductTour/Checkpoint.test.jsx +3 -2
  224. package/src/ProductTour/ProductTour.test.jsx +11 -24
  225. package/src/ProductTour/index.jsx +1 -1
  226. package/src/Scrollable/Scrollable.test.jsx +2 -2
  227. package/src/Scrollable/index.jsx +1 -1
  228. package/src/SearchField/index.scss +2 -1
  229. package/src/SelectableBox/tests/SelectableBox.test.jsx +3 -2
  230. package/src/StatusAlert/StatusAlert.test.jsx +6 -2
  231. package/src/Stepper/StepperHeader.jsx +1 -1
  232. package/src/Stepper/tests/Stepper.test.jsx +1 -1
  233. package/src/Table/_variables.scss +2 -1
  234. package/src/Tabs/Tabs.test.jsx +1 -1
  235. package/src/Tabs/deprecated/Tabs.test.jsx +6 -4
  236. package/src/Tabs/index.jsx +1 -1
  237. package/src/Toast/ToastContainer.scss +1 -1
  238. package/src/Toast/index.scss +2 -2
  239. package/src/Truncate/index.jsx +1 -1
  240. package/src/hooks/tests/useToggle.test.tsx +1 -1
  241. package/src/hooks/{useArrowKeyNavigation.tsx → useArrowKeyNavigationHook.tsx} +4 -0
  242. package/src/hooks/{useIndexOfLastVisibleChild.tsx → useIndexOfLastVisibleChildHook.tsx} +4 -0
  243. package/src/hooks/{useToggle.tsx → useToggleHook.tsx} +4 -0
  244. package/src/index.d.ts +6 -6
  245. package/src/index.js +6 -6
  246. package/dist/hooks/useArrowKeyNavigation.js.map +0 -1
  247. package/dist/hooks/useIndexOfLastVisibleChild.js.map +0 -1
  248. package/dist/hooks/useIsVisible.js.map +0 -1
  249. package/dist/hooks/useToggle.js.map +0 -1
  250. package/dist/hooks/useWindowSize.js.map +0 -1
  251. package/src/DataTable/tests/utils.js +0 -9
  252. /package/dist/hooks/{useArrowKeyNavigation.d.ts → useArrowKeyNavigationHook.d.ts} +0 -0
  253. /package/dist/hooks/{useIndexOfLastVisibleChild.d.ts → useIndexOfLastVisibleChildHook.d.ts} +0 -0
  254. /package/dist/hooks/{useIsVisible.d.ts → useIsVisibleHook.d.ts} +0 -0
  255. /package/dist/hooks/{useToggle.d.ts → useToggleHook.d.ts} +0 -0
  256. /package/dist/hooks/{useWindowSize.d.ts → useWindowSizeHook.d.ts} +0 -0
  257. /package/src/hooks/{useIsVisible.tsx → useIsVisibleHook.tsx} +0 -0
  258. /package/src/hooks/{useWindowSize.tsx → useWindowSizeHook.tsx} +0 -0
@@ -1,15 +1,19 @@
1
- import React from 'react';
1
+ import React, { forwardRef } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classNames from 'classnames';
4
+ import {
5
+ type BsPrefixRefForwardingComponent as ComponentWithAsProp,
6
+ type BsPrefixProps,
7
+ } from 'react-bootstrap/esm/helpers';
8
+ import { defineMessages, useIntl } from 'react-intl';
4
9
  import { Launch } from '../../icons';
5
10
  import Icon from '../Icon';
11
+ // @ts-ignore
12
+ import { customPropTypeRequirement } from '../utils/propTypes/utils';
6
13
 
7
- export const HYPER_LINK_EXTERNAL_LINK_ALT_TEXT = 'in a new tab';
8
- export const HYPER_LINK_EXTERNAL_LINK_TITLE = 'Opens in a new tab';
9
-
10
- interface Props extends Omit<React.ComponentPropsWithRef<'a'>, 'href' | 'target'> {
14
+ export interface HyperlinkProps extends BsPrefixProps, Omit<React.ComponentPropsWithRef<'a'>, 'href' | 'target'> {
11
15
  /** specifies the URL */
12
- destination: string;
16
+ destination?: string;
13
17
  /** Content of the hyperlink */
14
18
  children: React.ReactNode;
15
19
  /** Custom class names for the hyperlink */
@@ -24,22 +28,42 @@ interface Props extends Omit<React.ComponentPropsWithRef<'a'>, 'href' | 'target'
24
28
  isInline?: boolean;
25
29
  /** specify if we need to show launch Icon. By default, it will be visible. */
26
30
  showLaunchIcon?: boolean;
31
+ /** specifies where the link should open. The default behavior is `_self`, which means that the URL will be
32
+ * loaded into the same browsing context as the current one.
33
+ * If the target is `_blank` (opening a new window) `rel='noopener'` will be added to the anchor tag to prevent
34
+ * any potential [reverse tabnabbing attack](https://www.owasp.org/index.php/Reverse_Tabnabbing).
35
+ */
27
36
  target?: '_blank' | '_self';
28
37
  }
29
38
 
30
- const Hyperlink = React.forwardRef<HTMLAnchorElement, Props>(({
39
+ export type HyperlinkType = ComponentWithAsProp<'a', HyperlinkProps>;
40
+
41
+ const messages = defineMessages({
42
+ externalLinkAltText: {
43
+ id: 'Hyperlink.externalLinkAltText',
44
+ defaultMessage: 'in a new tab',
45
+ },
46
+ externalLinkTitle: {
47
+ id: 'Hyperlink.externalLinkTitle',
48
+ defaultMessage: 'Opens in a new tab',
49
+ },
50
+ });
51
+
52
+ const Hyperlink = forwardRef<HTMLAnchorElement, HyperlinkProps>(({
53
+ as: Component = 'a',
31
54
  className,
32
55
  destination,
33
56
  children,
34
- target,
57
+ target = '_self',
35
58
  onClick,
36
59
  externalLinkAlternativeText,
37
60
  externalLinkTitle,
38
- variant,
39
- isInline,
40
- showLaunchIcon,
61
+ variant = 'default',
62
+ isInline = false,
63
+ showLaunchIcon = true,
41
64
  ...attrs
42
65
  }, ref) => {
66
+ const intl = useIntl();
43
67
  let externalLinkIcon;
44
68
 
45
69
  if (target === '_blank') {
@@ -63,11 +87,11 @@ const Hyperlink = React.forwardRef<HTMLAnchorElement, Props>(({
63
87
  externalLinkIcon = (
64
88
  <span
65
89
  className="pgn__hyperlink__external-icon"
66
- title={externalLinkTitle}
90
+ title={externalLinkTitle || intl.formatMessage(messages.externalLinkTitle)}
67
91
  >
68
92
  <Icon
69
93
  src={Launch}
70
- screenReaderText={externalLinkAlternativeText}
94
+ screenReaderText={externalLinkAlternativeText || intl.formatMessage(messages.externalLinkAltText)}
71
95
  style={{ height: '1em', width: '1em' }}
72
96
  data-testid="hyperlink-icon"
73
97
  />
@@ -76,8 +100,13 @@ const Hyperlink = React.forwardRef<HTMLAnchorElement, Props>(({
76
100
  }
77
101
  }
78
102
 
103
+ const additionalProps: Record<string, any> = { ...attrs };
104
+ if (destination) {
105
+ additionalProps.href = destination;
106
+ }
107
+
79
108
  return (
80
- <a
109
+ <Component
81
110
  ref={ref}
82
111
  className={classNames(
83
112
  'pgn__hyperlink',
@@ -88,32 +117,29 @@ const Hyperlink = React.forwardRef<HTMLAnchorElement, Props>(({
88
117
  },
89
118
  className,
90
119
  )}
91
- href={destination}
92
120
  target={target}
93
121
  onClick={onClick}
94
- {...attrs}
122
+ {...additionalProps}
95
123
  >
96
124
  {children}
97
125
  {externalLinkIcon}
98
- </a>
126
+ </Component>
99
127
  );
100
128
  });
101
129
 
102
- Hyperlink.defaultProps = {
103
- className: undefined,
104
- target: '_self',
105
- onClick: () => {},
106
- externalLinkAlternativeText: HYPER_LINK_EXTERNAL_LINK_ALT_TEXT,
107
- externalLinkTitle: HYPER_LINK_EXTERNAL_LINK_TITLE,
108
- variant: 'default',
109
- isInline: false,
110
- showLaunchIcon: true,
111
- };
112
-
113
130
  Hyperlink.propTypes = {
114
- /** specifies the URL */
115
- destination: PropTypes.string.isRequired,
131
+ /** specifies the component element type to render for the hyperlink */
132
+ // @ts-ignore
133
+ as: PropTypes.elementType,
134
+ /** specifies the URL; required iff `as` prop is a standard anchor tag */
135
+ destination: customPropTypeRequirement(
136
+ PropTypes.string,
137
+ ({ as }: { as: React.ElementType }) => as && as === 'a',
138
+ // "[`destination` is required when]..."
139
+ 'the `as` prop is a standard anchor element (i.e., "a")',
140
+ ),
116
141
  /** Content of the hyperlink */
142
+ // @ts-ignore
117
143
  children: PropTypes.node.isRequired,
118
144
  /** Custom class names for the hyperlink */
119
145
  className: PropTypes.string,
@@ -137,4 +163,19 @@ Hyperlink.propTypes = {
137
163
  showLaunchIcon: PropTypes.bool,
138
164
  };
139
165
 
166
+ Hyperlink.defaultProps = {
167
+ as: 'a',
168
+ className: undefined,
169
+ destination: undefined,
170
+ externalLinkAlternativeText: undefined,
171
+ externalLinkTitle: undefined,
172
+ isInline: false,
173
+ onClick: undefined,
174
+ showLaunchIcon: true,
175
+ target: '_self',
176
+ variant: 'default',
177
+ };
178
+
179
+ Hyperlink.displayName = 'Hyperlink';
180
+
140
181
  export default Hyperlink;
@@ -21,7 +21,8 @@ describe('IconButtonToggle tests', () => {
21
21
  expect(btnAbc).toHaveClass('btn-icon-primary-active');
22
22
  expect(btnAbc).toHaveAttribute('aria-selected', 'true');
23
23
  });
24
- test('switching activeValue works as expected', () => {
24
+ test('switching activeValue works as expected', async () => {
25
+ const user = userEvent.setup();
25
26
  const spyChanger = jest.fn();
26
27
  render(
27
28
  <IconButtonToggle activeValue="abc" onChange={spyChanger}>
@@ -38,7 +39,7 @@ describe('IconButtonToggle tests', () => {
38
39
  expect(btnAbc).toHaveClass('btn-icon-primary-active');
39
40
  expect(btnAbc).toHaveAttribute('aria-selected', 'true');
40
41
 
41
- userEvent.click(btnDef);
42
+ await user.click(btnDef);
42
43
 
43
44
  waitFor(() => {
44
45
  expect(btnDef).toHaveClass('btn-icon-primary-active');
@@ -1,7 +1,9 @@
1
+ @use "sass:map";
2
+
1
3
  .pgn__icon-button-toggle__container {
2
4
  display: flex;
3
5
 
4
6
  .btn-icon + .btn-icon {
5
- margin-inline-start: map_get($spacers, 1);
7
+ margin-inline-start: map.get($spacers, 1);
6
8
  }
7
9
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { render, screen } from '@testing-library/react';
2
+ import { render, screen, waitFor } from '@testing-library/react';
3
3
  import userEvent from '@testing-library/user-event';
4
4
 
5
5
  import ListBox from '.';
@@ -82,15 +82,18 @@ describe('ListBox', () => {
82
82
 
83
83
  listBoxElement.focus();
84
84
 
85
- expect(listBoxElement.getAttribute('aria-activedescendant')).toEqual('list-box-option-0');
85
+ await waitFor(() => {
86
+ expect(listBoxElement.getAttribute('aria-activedescendant')).toEqual('list-box-option-0');
87
+ });
86
88
  });
87
89
 
88
90
  it('should not select first ListBoxOption on focus if ListBoxOption selected', async () => {
91
+ const user = userEvent.setup();
89
92
  const listBoxElement = screen.getByRole('listbox');
90
93
 
91
94
  listBoxElement.focus();
92
95
 
93
- await userEvent.keyboard('{arrowdown}');
96
+ await user.keyboard('{arrowdown}');
94
97
 
95
98
  listBoxElement.focus();
96
99
 
@@ -98,11 +101,12 @@ describe('ListBox', () => {
98
101
  });
99
102
 
100
103
  it('should select next ListBoxOption on down arrow key', async () => {
104
+ const user = userEvent.setup();
101
105
  const listBoxElement = screen.getByRole('listbox');
102
106
 
103
107
  listBoxElement.focus();
104
108
 
105
- await userEvent.keyboard('{arrowdown}');
109
+ await user.keyboard('{arrowdown}');
106
110
 
107
111
  expect(listBoxElement.getAttribute('aria-activedescendant')).toEqual('list-box-option-1');
108
112
  });
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
+ import { IntlProvider } from 'react-intl';
3
4
 
4
5
  import MailtoLink from '.';
5
6
 
@@ -11,10 +12,18 @@ const content = 'content';
11
12
 
12
13
  const baseProps = { subject, body, content };
13
14
 
15
+ function MailtoLinkWrapper(props) {
16
+ return (
17
+ <IntlProvider locale="en">
18
+ <MailtoLink {...props} />
19
+ </IntlProvider>
20
+ );
21
+ }
22
+
14
23
  describe('correct rendering', () => {
15
24
  it('renders MailtoLink with single to, cc, and bcc recipient', () => {
16
25
  const singleRecipientLink = (
17
- <MailtoLink
26
+ <MailtoLinkWrapper
18
27
  {...baseProps}
19
28
  to={emailAddress}
20
29
  cc={emailAddress}
@@ -31,7 +40,7 @@ describe('correct rendering', () => {
31
40
 
32
41
  it('renders mailtoLink with many to, cc, and bcc recipients', () => {
33
42
  const multiRecipientLink = (
34
- <MailtoLink
43
+ <MailtoLinkWrapper
35
44
  {...baseProps}
36
45
  to={emailAddresses}
37
46
  cc={emailAddresses}
@@ -46,7 +55,7 @@ describe('correct rendering', () => {
46
55
  });
47
56
 
48
57
  it('renders empty mailtoLink', () => {
49
- const { getByText } = render(<MailtoLink content={content} />);
58
+ const { getByText } = render(<MailtoLinkWrapper content={content} />);
50
59
  const linkElement = getByText('content');
51
60
  expect(linkElement.getAttribute('href')).toEqual('mailto:');
52
61
  });
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { IntlProvider } from 'react-intl';
2
3
  import { render, screen } from '@testing-library/react';
3
4
  import renderer from 'react-test-renderer';
4
5
  import userEvent from '@testing-library/user-event';
@@ -20,15 +21,17 @@ describe('Menu Item renders correctly', () => {
20
21
 
21
22
  it('renders as expected with menu items', () => {
22
23
  const tree = renderer.create((
23
- <Menu>
24
- <MenuItem> A Menu Item</MenuItem>
25
- <MenuItem iconBefore={Add} stoven>A Menu Item With an Icon Before</MenuItem>
26
- <MenuItem iconAfter={Check}>A Menu Item With an Icon After </MenuItem>
27
- <MenuItem disabled>A Disabled Menu Item</MenuItem>
28
- <MenuItem as={Hyperlink} destination="https://en.wikipedia.org/wiki/Hyperlink">A Link Menu Item</MenuItem>
29
- <MenuItem as={Button} variant="primary" size="inline">A Button Menu Item</MenuItem>
30
- <MenuItem as={Form.Checkbox}>A Checkbox Menu Item</MenuItem>
31
- </Menu>
24
+ <IntlProvider locale="en">
25
+ <Menu>
26
+ <MenuItem> A Menu Item</MenuItem>
27
+ <MenuItem iconBefore={Add} stoven>A Menu Item With an Icon Before</MenuItem>
28
+ <MenuItem iconAfter={Check}>A Menu Item With an Icon After </MenuItem>
29
+ <MenuItem disabled>A Disabled Menu Item</MenuItem>
30
+ <MenuItem as={Hyperlink} destination="https://en.wikipedia.org/wiki/Hyperlink">A Link Menu Item</MenuItem>
31
+ <MenuItem as={Button} variant="primary" size="inline">A Button Menu Item</MenuItem>
32
+ <MenuItem as={Form.Checkbox}>A Checkbox Menu Item</MenuItem>
33
+ </Menu>
34
+ </IntlProvider>
32
35
  )).toJSON();
33
36
  expect(tree).toMatchSnapshot();
34
37
  });
@@ -71,48 +74,53 @@ describe('Keyboard Interactions', () => {
71
74
  expect(defaultItem).toHaveFocus();
72
75
  });
73
76
 
74
- it('should focus the next item after ArrowDown keyDown', () => {
77
+ it('should focus the next item after ArrowDown keyDown', async () => {
78
+ const user = userEvent.setup();
75
79
  const defaultItem = screen.getByText('Default');
76
80
  const cantTouchThisItem = screen.getByText(MENU_ITEM_TEXT).parentElement;
77
81
 
78
- userEvent.type(defaultItem, '{arrowdown}');
82
+ await user.type(defaultItem, '{arrowdown}');
79
83
 
80
84
  expect(cantTouchThisItem).toHaveFocus();
81
85
  });
82
86
 
83
- it('should focus the next item after Tab keyDown', () => {
87
+ it('should focus the next item after Tab keyDown', async () => {
88
+ const user = userEvent.setup();
84
89
  const defaultItem = screen.getByText('Default').parentElement;
85
90
  const cantTouchThisItem = screen.getByText(MENU_ITEM_TEXT).parentElement;
86
91
  defaultItem.focus();
87
- userEvent.tab();
92
+ await user.tab();
88
93
 
89
94
  expect(cantTouchThisItem).toHaveFocus();
90
95
  });
91
96
 
92
- it('should loop focus to the first item after Tab keyDown on last item', () => {
97
+ it('should loop focus to the first item after Tab keyDown on last item', async () => {
98
+ const user = userEvent.setup();
93
99
  const defaultItem = screen.getByText('Default').parentElement;
94
100
  const iconBeforeItem = screen.getByText('Icon Before');
95
101
  iconBeforeItem.focus();
96
- userEvent.tab();
102
+ await user.tab();
97
103
 
98
104
  expect(defaultItem).toHaveFocus();
99
105
  });
100
106
 
101
- it('should loop focus to the last item after ArrowUp keyDown on first item', () => {
107
+ it('should loop focus to the last item after ArrowUp keyDown on first item', async () => {
108
+ const user = userEvent.setup();
102
109
  const defaultItem = screen.getByText('Default').parentElement;
103
110
  const iconBeforeItem = screen.getByText('Icon Before').parentElement;
104
111
  defaultItem.focus();
105
- userEvent.type(defaultItem, '{arrowup}');
112
+ await user.type(defaultItem, '{arrowup}');
106
113
 
107
114
  expect(iconBeforeItem).toHaveFocus();
108
115
  });
109
116
 
110
- it('should focus the previous item after Shift + Tab keyDown', () => {
117
+ it('should focus the previous item after Shift + Tab keyDown', async () => {
118
+ const user = userEvent.setup();
111
119
  const button1 = screen.getAllByRole('button')[0];
112
120
  const button2 = screen.getAllByRole('button')[1];
113
121
 
114
122
  button2.focus();
115
- userEvent.tab({ shift: true });
123
+ await user.tab({ shift: true });
116
124
 
117
125
  expect(button1).toHaveFocus();
118
126
  });
@@ -4,7 +4,7 @@ import classNames from 'classnames';
4
4
  import { ExpandMore } from '../../icons';
5
5
  import Button from '../Button';
6
6
  import ModalPopup from '../Modal/ModalPopup';
7
- import useToggle from '../hooks/useToggle';
7
+ import useToggle from '../hooks/useToggleHook';
8
8
  import Menu from '.';
9
9
  import withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps';
10
10
 
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
+ import { IntlProvider } from 'react-intl';
3
+ import PropTypes from 'prop-types';
2
4
  import { render, screen } from '@testing-library/react';
3
5
  import renderer from 'react-test-renderer';
4
6
  import userEvent from '@testing-library/user-event';
@@ -10,27 +12,44 @@ import Hyperlink from '../Hyperlink';
10
12
  const app = document.createElement('div');
11
13
  document.body.appendChild(app);
12
14
 
15
+ function SelectMenuWrapper({ children }) {
16
+ return (
17
+ <IntlProvider locale="en">
18
+ {children}
19
+ </IntlProvider>
20
+ );
21
+ }
22
+ SelectMenuWrapper.propTypes = {
23
+ children: PropTypes.node.isRequired,
24
+ };
25
+
13
26
  function DefaultSelectMenu(props) {
14
- return <SelectMenu {...props}><MenuItem>A Menu Item</MenuItem></SelectMenu>;
27
+ return (
28
+ <SelectMenuWrapper>
29
+ <SelectMenu {...props}><MenuItem>A Menu Item</MenuItem></SelectMenu>
30
+ </SelectMenuWrapper>
31
+ );
15
32
  }
16
33
 
17
34
  function defaultSelectMenu() {
18
35
  return (
19
- <SelectMenu>
20
- <MenuItem>A Menu Item</MenuItem>
21
- <MenuItem iconBefore={Add}>A Menu Item With an Icon Before</MenuItem>
22
- <MenuItem iconAfter={Check}>A Menu Item With an Icon After </MenuItem>
23
- <MenuItem disabled>A Disabled Menu Item</MenuItem>
24
- <MenuItem as={Hyperlink} destination="https://en.wikipedia.org/wiki/Hyperlink">A Link Menu Item</MenuItem>
25
- <MenuItem>Falstaff</MenuItem>
26
- <MenuItem>Scipio</MenuItem>
27
- <MenuItem>Faustus</MenuItem>
28
- <MenuItem>Cordelia</MenuItem>
29
- <MenuItem>Renfrancine</MenuItem>
30
- <MenuItem>Stovern</MenuItem>
31
- <MenuItem>Kainian</MenuItem>
32
- <MenuItem>M. Hortens</MenuItem>
33
- </SelectMenu>
36
+ <SelectMenuWrapper>
37
+ <SelectMenu>
38
+ <MenuItem>A Menu Item</MenuItem>
39
+ <MenuItem iconBefore={Add}>A Menu Item With an Icon Before</MenuItem>
40
+ <MenuItem iconAfter={Check}>A Menu Item With an Icon After </MenuItem>
41
+ <MenuItem disabled>A Disabled Menu Item</MenuItem>
42
+ <MenuItem as={Hyperlink} destination="https://en.wikipedia.org/wiki/Hyperlink">A Link Menu Item</MenuItem>
43
+ <MenuItem>Falstaff</MenuItem>
44
+ <MenuItem>Scipio</MenuItem>
45
+ <MenuItem>Faustus</MenuItem>
46
+ <MenuItem>Cordelia</MenuItem>
47
+ <MenuItem>Renfrancine</MenuItem>
48
+ <MenuItem>Stovern</MenuItem>
49
+ <MenuItem>Kainian</MenuItem>
50
+ <MenuItem>M. Hortens</MenuItem>
51
+ </SelectMenu>
52
+ </SelectMenuWrapper>
34
53
  );
35
54
  }
36
55
 
@@ -95,7 +95,6 @@ exports[`Menu Item renders correctly renders as expected with menu items 1`] = `
95
95
  <a
96
96
  className="pgn__hyperlink default-link standalone-link pgn__menu-item"
97
97
  href="https://en.wikipedia.org/wiki/Hyperlink"
98
- onClick={[Function]}
99
98
  target="_self"
100
99
  >
101
100
  <span
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classNames from 'classnames';
4
- import useArrowKeyNavigation from '../hooks/useArrowKeyNavigation';
4
+ import useArrowKeyNavigation from '../hooks/useArrowKeyNavigationHook';
5
5
 
6
6
  function Menu({
7
7
  as,
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classNames from 'classnames';
4
- import useIsVisible from '../hooks/useIsVisible';
4
+ import useIsVisible from '../hooks/useIsVisibleHook';
5
5
 
6
6
  function ModalDialogBody({
7
7
  as,
@@ -1,3 +1,5 @@
1
+ @use "sass:map";
2
+
1
3
  .pgn__modal {
2
4
  background: $modal-content-bg;
3
5
  border-radius: $modal-content-inner-border-radius;
@@ -315,7 +317,7 @@
315
317
 
316
318
  .pgn__alert-modal__title_icon {
317
319
  flex-shrink: 0;
318
- margin-right: map-get($spacers, 2\.5);
320
+ margin-right: map.get($spacers, 2\.5);
319
321
  }
320
322
  }
321
323
  }
@@ -50,6 +50,8 @@ class Modal extends React.Component {
50
50
 
51
51
  componentWillUnmount() {
52
52
  if (this.parentElement) {
53
+ // TODO: update this to use the new createRoot() compatible APIs.
54
+ // eslint-disable-next-line react/no-deprecated
53
55
  ReactDOM.unmountComponentAtNode(this.parentElement);
54
56
  }
55
57
  }
@@ -1,3 +1,4 @@
1
+ @use "sass:map";
1
2
  @import "variables";
2
3
  @import "~bootstrap/scss/modal";
3
4
  @import "ModalDialog";
@@ -19,12 +20,9 @@
19
20
 
20
21
  .pgn__modal-backdrop {
21
22
  background: $modal-backdrop-bg;
22
- bottom: 0;
23
- left: 0;
23
+ inset: 0;
24
24
  opacity: $modal-backdrop-opacity;
25
25
  position: fixed;
26
- right: 0;
27
- top: 0;
28
26
  z-index: 0;
29
27
  }
30
28
 
@@ -88,7 +86,7 @@
88
86
  margin: auto;
89
87
  padding: calc($spacer / 2);
90
88
 
91
- @media (min-width: map-get($grid-breakpoints, "sm")) {
89
+ @media (min-width: map.get($grid-breakpoints, "sm")) {
92
90
  padding: $spacer;
93
91
  }
94
92
  }
@@ -78,7 +78,8 @@ describe('<ModalLayer />', () => {
78
78
  });
79
79
 
80
80
  describe('Dismiss modal', () => {
81
- it('closes a non-blocking modal layer when backdrop is clicked', () => {
81
+ it('closes a non-blocking modal layer when backdrop is clicked', async () => {
82
+ const user = userEvent.setup();
82
83
  const closeFn = jest.fn();
83
84
  render(
84
85
  <ModalLayer isOpen onClose={closeFn} isBlocking={false}>
@@ -86,7 +87,7 @@ describe('<ModalLayer />', () => {
86
87
  </ModalLayer>,
87
88
  );
88
89
  const backdrop = screen.getByTestId('modal-backdrop');
89
- userEvent.click(backdrop);
90
+ await user.click(backdrop);
90
91
  expect(closeFn).toHaveBeenCalled();
91
92
  });
92
93
 
@@ -1,3 +1,5 @@
1
+ @use "sass:map";
2
+
1
3
  @mixin nav-tabs-link-focus(
2
4
  $border-color,
3
5
  $radius: $nav-tabs-border-radius,
@@ -5,7 +7,7 @@
5
7
  ) {
6
8
  position: relative;
7
9
  outline: 0;
8
- z-index: map-get($map: $indexes, $key: 1);
10
+ z-index: map.get($map: $indexes, $key: 1);
9
11
 
10
12
  &::before {
11
13
  content: "";
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
- import { renderHook } from '@testing-library/react-hooks/dom';
3
- import { act } from '@testing-library/react';
2
+ import { act, renderHook } from '@testing-library/react';
4
3
  import useOverflowScroll from '../useOverflowScroll';
5
4
  import useOverflowScrollActions from '../useOverflowScrollActions';
6
5
  import getChildrenElements from '../getChildrenElements';
@@ -1,4 +1,4 @@
1
- import { renderHook } from '@testing-library/react-hooks/dom';
1
+ import { renderHook } from '@testing-library/react';
2
2
  import { act } from 'react-test-renderer';
3
3
  import useOverflowScrollActions from '../useOverflowScrollActions';
4
4
 
@@ -1,4 +1,4 @@
1
- import { renderHook } from '@testing-library/react-hooks/dom';
1
+ import { renderHook } from '@testing-library/react';
2
2
  import useOverflowScrollElementAttributes, {
3
3
  OVERFLOW_SCROLL_OVERFLOW_CONTAINER_CLASS,
4
4
  OVERFLOW_SCROLL_OVERFLOW_OPACITY_MASK_GRADIENT_START,
@@ -1,5 +1,4 @@
1
- import { renderHook } from '@testing-library/react-hooks/dom';
2
- import { act } from '@testing-library/react';
1
+ import { act, renderHook } from '@testing-library/react';
3
2
  import useOverflowScrollEventListeners from '../useOverflowScrollEventListeners';
4
3
 
5
4
  const divElement = document.createElement('div');
@@ -1,3 +1,4 @@
1
+ @use "sass:map";
1
2
  // stylelint-disable-next-line selector-class-pattern
2
3
  .pgn__pageBanner-component {
3
4
  width: 100%;
@@ -46,7 +47,7 @@
46
47
  flex-grow: 1;
47
48
  justify-content: center;
48
49
  align-items: center;
49
- padding: map_get($spacers, 2) map_get($spacers, 2\.5);
50
+ padding: map.get($spacers, 2) map.get($spacers, 2\.5);
50
51
  text-align: center;
51
52
  }
52
53