@openedx/paragon 22.0.0-alpha.22 → 22.0.0-alpha.24

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 (309) hide show
  1. package/bin/paragon-scripts.js +12 -1
  2. package/dist/Button/index.js +2 -2
  3. package/dist/Button/index.js.map +1 -1
  4. package/dist/Button/index.scss +3 -3
  5. package/dist/ColorPicker/index.js +48 -18
  6. package/dist/ColorPicker/index.js.map +1 -1
  7. package/dist/Container/index.js +6 -2
  8. package/dist/Container/index.js.map +1 -1
  9. package/dist/DataTable/index.js +2 -1
  10. package/dist/DataTable/index.js.map +1 -1
  11. package/dist/DataTable/selection/BaseSelectionStatus.js +3 -2
  12. package/dist/DataTable/selection/BaseSelectionStatus.js.map +1 -1
  13. package/dist/Dropdown/index.js.map +1 -1
  14. package/dist/Dropzone/index.js +2 -3
  15. package/dist/Dropzone/index.js.map +1 -1
  16. package/dist/Form/FormAutosuggest.js +9 -4
  17. package/dist/Form/FormAutosuggest.js.map +1 -1
  18. package/dist/Form/FormSwitch.js +3 -0
  19. package/dist/Form/FormSwitch.js.map +1 -1
  20. package/dist/Hyperlink/index.js +7 -6
  21. package/dist/Hyperlink/index.js.map +1 -1
  22. package/dist/Icon/index.js +18 -11
  23. package/dist/Icon/index.js.map +1 -1
  24. package/dist/IconButton/index.js +1 -1
  25. package/dist/IconButton/index.js.map +1 -1
  26. package/dist/Layout/index.js.map +1 -1
  27. package/dist/Menu/MenuItem.js +2 -2
  28. package/dist/Menu/MenuItem.js.map +1 -1
  29. package/dist/Modal/ModalDialog.js +3 -0
  30. package/dist/Modal/ModalDialog.js.map +1 -1
  31. package/dist/Modal/_ModalDialog.scss +12 -20
  32. package/dist/Popover/index.js +8 -8
  33. package/dist/Popover/index.js.map +1 -1
  34. package/dist/ProductTour/Checkpoint.js +10 -8
  35. package/dist/ProductTour/Checkpoint.js.map +1 -1
  36. package/dist/ProductTour/messages.js +16 -0
  37. package/dist/SearchField/SearchFieldAdvanced.js +12 -7
  38. package/dist/SearchField/SearchFieldAdvanced.js.map +1 -1
  39. package/dist/SearchField/SearchFieldLabel.js +3 -3
  40. package/dist/SearchField/SearchFieldLabel.js.map +1 -1
  41. package/dist/SearchField/index.js +0 -1
  42. package/dist/SearchField/index.js.map +1 -1
  43. package/dist/SelectableBox/index.js +9 -5
  44. package/dist/SelectableBox/index.js.map +1 -1
  45. package/dist/Tabs/index.js +13 -13
  46. package/dist/Tabs/index.js.map +1 -1
  47. package/dist/core.css +17 -18
  48. package/dist/core.css.map +1 -1
  49. package/dist/core.min.css +1 -1
  50. package/dist/hooks/useIndexOfLastVisibleChild.js +33 -38
  51. package/dist/hooks/useIndexOfLastVisibleChild.js.map +1 -1
  52. package/dist/i18n/messages/ar.json +2 -1
  53. package/dist/i18n/messages/ca.json +2 -1
  54. package/dist/i18n/messages/es_419.json +2 -1
  55. package/dist/i18n/messages/es_AR.json +2 -1
  56. package/dist/i18n/messages/es_ES.json +2 -1
  57. package/dist/i18n/messages/fr.json +2 -1
  58. package/dist/i18n/messages/he.json +2 -1
  59. package/dist/i18n/messages/id.json +2 -1
  60. package/dist/i18n/messages/it_IT.json +2 -1
  61. package/dist/i18n/messages/ko_KR.json +2 -1
  62. package/dist/i18n/messages/pl.json +2 -1
  63. package/dist/i18n/messages/pt_BR.json +2 -1
  64. package/dist/i18n/messages/pt_PT.json +2 -1
  65. package/dist/i18n/messages/ru.json +2 -1
  66. package/dist/i18n/messages/th.json +2 -1
  67. package/dist/i18n/messages/tr_TR.json +2 -1
  68. package/dist/i18n/messages/uk.json +2 -1
  69. package/dist/i18n/messages/zh_CN.json +2 -1
  70. package/dist/light.css +11 -11
  71. package/dist/light.css.map +1 -1
  72. package/dist/light.min.css +1 -1
  73. package/icons/.svgrrc.js +1 -1
  74. package/icons/es5/Accessible.js +2 -1
  75. package/icons/es5/AccessibleForward.js +2 -1
  76. package/icons/es5/AssistWalker.js +2 -1
  77. package/icons/es5/Attribution.js +2 -1
  78. package/icons/es5/Bathtub.js +2 -1
  79. package/icons/es5/Biotech.js +2 -1
  80. package/icons/es5/Blind.js +2 -1
  81. package/icons/es5/BlurOff.js +16 -8
  82. package/icons/es5/Brightness1.js +2 -1
  83. package/icons/es5/BubbleChart.js +6 -3
  84. package/icons/es5/CameraAlt.js +2 -1
  85. package/icons/es5/Category.js +2 -1
  86. package/icons/es5/CheckCircleLightOutline.js +12 -17
  87. package/icons/es5/ChildCare.js +4 -2
  88. package/icons/es5/CoPresent.js +2 -1
  89. package/icons/es5/CoffeeMaker.js +2 -1
  90. package/icons/es5/CompassCalibration.js +2 -1
  91. package/icons/es5/ControlCamera.js +2 -1
  92. package/icons/es5/Deblur.js +24 -12
  93. package/icons/es5/Diversity1.js +4 -2
  94. package/icons/es5/EmojiPeople.js +2 -1
  95. package/icons/es5/EmojiSymbols.js +4 -2
  96. package/icons/es5/Face2.js +4 -2
  97. package/icons/es5/Face3.js +4 -2
  98. package/icons/es5/Face4.js +4 -2
  99. package/icons/es5/Face5.js +44 -22
  100. package/icons/es5/Face6.js +4 -2
  101. package/icons/es5/FaceRetouchingNatural.js +4 -2
  102. package/icons/es5/FaceRetouchingOff.js +2 -1
  103. package/icons/es5/FiberManualRecord.js +2 -1
  104. package/icons/es5/FiberSmartRecord.js +2 -1
  105. package/icons/es5/FireHydrantAlt.js +2 -1
  106. package/icons/es5/Garage.js +4 -2
  107. package/icons/es5/GolfCourse.js +2 -1
  108. package/icons/es5/HotTub.js +2 -1
  109. package/icons/es5/LinkedCamera.js +2 -1
  110. package/icons/es5/LocalSee.js +2 -1
  111. package/icons/es5/Man.js +2 -1
  112. package/icons/es5/Man2.js +2 -1
  113. package/icons/es5/Man4.js +2 -1
  114. package/icons/es5/ManageAccounts.js +2 -1
  115. package/icons/es5/MarkUnreadChatAlt.js +2 -1
  116. package/icons/es5/NoiseAware.js +2 -1
  117. package/icons/es5/NoiseControlOff.js +2 -1
  118. package/icons/es5/PeopleAlt.js +2 -1
  119. package/icons/es5/PersonSearch.js +2 -1
  120. package/icons/es5/Pets.js +8 -4
  121. package/icons/es5/Plagiarism.js +2 -1
  122. package/icons/es5/Policy.js +2 -1
  123. package/icons/es5/Pool.js +2 -1
  124. package/icons/es5/PriorityHigh.js +2 -1
  125. package/icons/es5/RecordVoiceOver.js +2 -1
  126. package/icons/es5/RememberMe.js +2 -1
  127. package/icons/es5/ReportGmailerrorred.js +2 -1
  128. package/icons/es5/RightSidebarFilled.js +15 -0
  129. package/icons/es5/RightSidebarOutlined.js +15 -0
  130. package/icons/es5/RssFeed.js +2 -1
  131. package/icons/es5/ScatterPlot.js +6 -3
  132. package/icons/es5/ScreenSearchDesktop.js +2 -1
  133. package/icons/es5/SelfImprovement.js +2 -1
  134. package/icons/es5/SentimentDissatisfied.js +4 -2
  135. package/icons/es5/SentimentSatisfied.js +4 -2
  136. package/icons/es5/SentimentSatisfiedAlt.js +4 -2
  137. package/icons/es5/SentimentSlightlyDissatisfied.js +4 -2
  138. package/icons/es5/SettingsApplications.js +2 -1
  139. package/icons/es5/Shower.js +12 -6
  140. package/icons/es5/SpatialAudio.js +2 -1
  141. package/icons/es5/SpatialAudioOff.js +2 -1
  142. package/icons/es5/SpatialTracking.js +2 -1
  143. package/icons/es5/SpeakerGroup.js +2 -1
  144. package/icons/es5/Sports.js +2 -1
  145. package/icons/es5/SportsCricket.js +2 -1
  146. package/icons/es5/SportsGolf.js +6 -3
  147. package/icons/es5/SportsKabaddi.js +2 -1
  148. package/icons/es5/SportsMartialArts.js +2 -1
  149. package/icons/es5/Stream.js +8 -4
  150. package/icons/es5/Streetview.js +2 -1
  151. package/icons/es5/Subway.js +4 -2
  152. package/icons/es5/SupportAgent.js +4 -2
  153. package/icons/es5/WindPower.js +2 -1
  154. package/icons/es5/Woman.js +2 -1
  155. package/icons/es5/Woman2.js +2 -1
  156. package/icons/es5/Yard.js +2 -1
  157. package/icons/es5/index.js +4 -2
  158. package/icons/jsx/Accessible.jsx +1 -1
  159. package/icons/jsx/AccessibleForward.jsx +1 -1
  160. package/icons/jsx/AssistWalker.jsx +1 -1
  161. package/icons/jsx/Attribution.jsx +1 -1
  162. package/icons/jsx/Bathtub.jsx +1 -1
  163. package/icons/jsx/Biotech.jsx +1 -1
  164. package/icons/jsx/Blind.jsx +1 -1
  165. package/icons/jsx/BlurOff.jsx +8 -8
  166. package/icons/jsx/Brightness1.jsx +1 -1
  167. package/icons/jsx/BubbleChart.jsx +3 -3
  168. package/icons/jsx/CameraAlt.jsx +1 -1
  169. package/icons/jsx/Category.jsx +1 -1
  170. package/icons/jsx/CheckCircleLightOutline.jsx +9 -16
  171. package/icons/jsx/ChildCare.jsx +2 -2
  172. package/icons/jsx/CoPresent.jsx +1 -1
  173. package/icons/jsx/CoffeeMaker.jsx +1 -1
  174. package/icons/jsx/CompassCalibration.jsx +1 -1
  175. package/icons/jsx/ControlCamera.jsx +1 -1
  176. package/icons/jsx/Deblur.jsx +12 -12
  177. package/icons/jsx/Diversity1.jsx +2 -2
  178. package/icons/jsx/EmojiPeople.jsx +1 -1
  179. package/icons/jsx/EmojiSymbols.jsx +2 -2
  180. package/icons/jsx/Face2.jsx +2 -2
  181. package/icons/jsx/Face3.jsx +2 -2
  182. package/icons/jsx/Face4.jsx +2 -2
  183. package/icons/jsx/Face5.jsx +22 -22
  184. package/icons/jsx/Face6.jsx +2 -2
  185. package/icons/jsx/FaceRetouchingNatural.jsx +2 -2
  186. package/icons/jsx/FaceRetouchingOff.jsx +1 -1
  187. package/icons/jsx/FiberManualRecord.jsx +1 -1
  188. package/icons/jsx/FiberSmartRecord.jsx +1 -1
  189. package/icons/jsx/FireHydrantAlt.jsx +1 -1
  190. package/icons/jsx/Garage.jsx +2 -2
  191. package/icons/jsx/GolfCourse.jsx +1 -1
  192. package/icons/jsx/HotTub.jsx +1 -1
  193. package/icons/jsx/LinkedCamera.jsx +1 -1
  194. package/icons/jsx/LocalSee.jsx +1 -1
  195. package/icons/jsx/Man.jsx +1 -1
  196. package/icons/jsx/Man2.jsx +1 -1
  197. package/icons/jsx/Man4.jsx +1 -1
  198. package/icons/jsx/ManageAccounts.jsx +1 -1
  199. package/icons/jsx/MarkUnreadChatAlt.jsx +1 -1
  200. package/icons/jsx/NoiseAware.jsx +1 -1
  201. package/icons/jsx/NoiseControlOff.jsx +1 -1
  202. package/icons/jsx/PeopleAlt.jsx +1 -1
  203. package/icons/jsx/PersonSearch.jsx +1 -1
  204. package/icons/jsx/Pets.jsx +4 -4
  205. package/icons/jsx/Plagiarism.jsx +1 -1
  206. package/icons/jsx/Policy.jsx +1 -1
  207. package/icons/jsx/Pool.jsx +1 -1
  208. package/icons/jsx/PriorityHigh.jsx +1 -1
  209. package/icons/jsx/RecordVoiceOver.jsx +1 -1
  210. package/icons/jsx/RememberMe.jsx +1 -1
  211. package/icons/jsx/ReportGmailerrorred.jsx +1 -1
  212. package/icons/jsx/RightSidebarFilled.jsx +19 -0
  213. package/icons/jsx/RightSidebarOutlined.jsx +19 -0
  214. package/icons/jsx/RssFeed.jsx +1 -1
  215. package/icons/jsx/ScatterPlot.jsx +3 -3
  216. package/icons/jsx/ScreenSearchDesktop.jsx +1 -1
  217. package/icons/jsx/SelfImprovement.jsx +1 -1
  218. package/icons/jsx/SentimentDissatisfied.jsx +2 -2
  219. package/icons/jsx/SentimentSatisfied.jsx +2 -2
  220. package/icons/jsx/SentimentSatisfiedAlt.jsx +2 -2
  221. package/icons/jsx/SentimentSlightlyDissatisfied.jsx +2 -2
  222. package/icons/jsx/SettingsApplications.jsx +1 -1
  223. package/icons/jsx/Shower.jsx +6 -6
  224. package/icons/jsx/SpatialAudio.jsx +1 -1
  225. package/icons/jsx/SpatialAudioOff.jsx +1 -1
  226. package/icons/jsx/SpatialTracking.jsx +1 -1
  227. package/icons/jsx/SpeakerGroup.jsx +1 -1
  228. package/icons/jsx/Sports.jsx +1 -1
  229. package/icons/jsx/SportsCricket.jsx +1 -1
  230. package/icons/jsx/SportsGolf.jsx +3 -3
  231. package/icons/jsx/SportsKabaddi.jsx +1 -1
  232. package/icons/jsx/SportsMartialArts.jsx +1 -1
  233. package/icons/jsx/Stream.jsx +4 -4
  234. package/icons/jsx/Streetview.jsx +1 -1
  235. package/icons/jsx/Subway.jsx +2 -2
  236. package/icons/jsx/SupportAgent.jsx +2 -2
  237. package/icons/jsx/WindPower.jsx +1 -1
  238. package/icons/jsx/Woman.jsx +1 -1
  239. package/icons/jsx/Woman2.jsx +1 -1
  240. package/icons/jsx/Yard.jsx +1 -1
  241. package/icons/jsx/index.jsx +2 -0
  242. package/icons/svg/check_circle_light_outline.svg +13 -0
  243. package/icons/svg/right_sidebar_filled.svg +3 -0
  244. package/icons/svg/right_sidebar_outlined.svg +3 -0
  245. package/lib/version.js +9 -0
  246. package/package.json +3 -3
  247. package/src/Button/README.md +99 -92
  248. package/src/Button/index.jsx +2 -2
  249. package/src/Button/index.scss +3 -3
  250. package/src/ColorPicker/ColorPicker.test.jsx +24 -2
  251. package/src/ColorPicker/index.jsx +56 -16
  252. package/src/Container/index.jsx +4 -0
  253. package/src/DataTable/README.md +4 -4
  254. package/src/DataTable/index.jsx +2 -1
  255. package/src/DataTable/selection/BaseSelectionStatus.jsx +2 -2
  256. package/src/DataTable/tablefilters.mdx +3 -3
  257. package/src/DataTable/tests/DataTable.test.jsx +31 -0
  258. package/src/Dropdown/index.jsx +4 -0
  259. package/src/Dropzone/index.jsx +2 -3
  260. package/src/Form/FormAutosuggest.jsx +11 -5
  261. package/src/Form/FormSwitch.jsx +3 -0
  262. package/src/Form/form-autosuggest.mdx +80 -72
  263. package/src/Form/tests/FormAutosuggest.test.jsx +21 -0
  264. package/src/Hyperlink/index.jsx +7 -6
  265. package/src/Icon/index.jsx +18 -11
  266. package/src/IconButton/index.jsx +1 -1
  267. package/src/Layout/index.jsx +1 -4
  268. package/src/Menu/MenuItem.jsx +2 -2
  269. package/src/Modal/ModalDialog.jsx +3 -0
  270. package/src/Modal/_ModalDialog.scss +12 -20
  271. package/src/Overlay/README.md +1 -1
  272. package/src/Popover/README.md +0 -1
  273. package/src/Popover/index.jsx +11 -11
  274. package/src/ProductTour/Checkpoint.jsx +9 -6
  275. package/src/ProductTour/messages.js +16 -0
  276. package/src/SearchField/SearchFieldAdvanced.jsx +12 -7
  277. package/src/SearchField/SearchFieldLabel.jsx +3 -3
  278. package/src/SearchField/index.jsx +0 -1
  279. package/src/SelectableBox/README.md +103 -71
  280. package/src/SelectableBox/index.jsx +5 -1
  281. package/src/SelectableBox/tests/SelectableBox.test.jsx +7 -0
  282. package/src/SelectableBox/tests/SelectableBoxSet.test.jsx +1 -1
  283. package/src/Tabs/README.md +76 -0
  284. package/src/Tabs/index.jsx +19 -13
  285. package/src/hooks/tests/useIndexOfLastVisibleChild.test.jsx +3 -3
  286. package/src/hooks/useIndexOfLastVisibleChild.jsx +36 -38
  287. package/src/hooks/useIndexOfLastVisibleChild.mdx +3 -3
  288. package/src/i18n/messages/ar.json +2 -1
  289. package/src/i18n/messages/ca.json +2 -1
  290. package/src/i18n/messages/es_419.json +2 -1
  291. package/src/i18n/messages/es_AR.json +2 -1
  292. package/src/i18n/messages/es_ES.json +2 -1
  293. package/src/i18n/messages/fr.json +2 -1
  294. package/src/i18n/messages/he.json +2 -1
  295. package/src/i18n/messages/id.json +2 -1
  296. package/src/i18n/messages/it_IT.json +2 -1
  297. package/src/i18n/messages/ko_KR.json +2 -1
  298. package/src/i18n/messages/pl.json +2 -1
  299. package/src/i18n/messages/pt_BR.json +2 -1
  300. package/src/i18n/messages/pt_PT.json +2 -1
  301. package/src/i18n/messages/ru.json +2 -1
  302. package/src/i18n/messages/th.json +2 -1
  303. package/src/i18n/messages/tr_TR.json +2 -1
  304. package/src/i18n/messages/uk.json +2 -1
  305. package/src/i18n/messages/zh_CN.json +2 -1
  306. package/styles/css/core/variables.css +5 -3
  307. package/styles/css/themes/light/variables.css +11 -11
  308. package/tokens/src/core/components/Button/core.json +8 -4
  309. package/tokens/src/themes/light/alias/color.json +10 -10
@@ -10,6 +10,7 @@ import CheckpointActionRow from './CheckpointActionRow';
10
10
  import CheckpointBody from './CheckpointBody';
11
11
  import CheckpointBreadcrumbs from './CheckpointBreadcrumbs';
12
12
  import CheckpointTitle from './CheckpointTitle';
13
+ import messages from './messages';
13
14
 
14
15
  const Checkpoint = React.forwardRef(({
15
16
  body,
@@ -99,10 +100,8 @@ const Checkpoint = React.forwardRef(({
99
100
  >
100
101
  <span className="sr-only">
101
102
  <FormattedMessage
102
- id="pgn.ProductTour.Checkpoint.position-text"
103
- defaultMessage="Top of step {step}"
104
- value={{ step: index + 1 }}
105
- description="Screen-reader message to indicate the user's position in a sequence of checkpoints."
103
+ {...messages.topPositionText}
104
+ values={{ step: index + 1 }}
106
105
  />
107
106
  </span>
108
107
  {(title || !isOnlyCheckpoint) && (
@@ -118,8 +117,12 @@ const Checkpoint = React.forwardRef(({
118
117
  {...props}
119
118
  />
120
119
  <div id="pgn__checkpoint-arrow" data-popper-arrow />
121
- {/* This text is not translated due to Paragon's lack of i18n support */}
122
- <span className="sr-only">Bottom of step {index + 1}</span>
120
+ <span className="sr-only">
121
+ <FormattedMessage
122
+ {...messages.bottomPositionText}
123
+ values={{ step: index + 1 }}
124
+ />
125
+ </span>
123
126
  </div>
124
127
  );
125
128
  });
@@ -0,0 +1,16 @@
1
+ import { defineMessages } from 'react-intl';
2
+
3
+ const messages = defineMessages({
4
+ topPositionText: {
5
+ id: 'pgn.ProductTour.Checkpoint.top-position-text',
6
+ defaultMessage: 'Top of step {step}',
7
+ description: 'Screen-reader message to notify user that they are located at the bottom of the product tour step.',
8
+ },
9
+ bottomPositionText: {
10
+ id: 'pgn.ProductTour.Checkpoint.bottom-position-text',
11
+ defaultMessage: 'Bottom of step {step}',
12
+ description: 'Screen-reader message to notify user that they are located at the bottom of the product tour step.',
13
+ },
14
+ });
15
+
16
+ export default messages;
@@ -1,4 +1,3 @@
1
- /* eslint-disable max-len */
2
1
  import React, {
3
2
  useRef, createContext, useState, useEffect,
4
3
  } from 'react';
@@ -138,27 +137,32 @@ SearchFieldAdvanced.propTypes = {
138
137
  onSubmit: PropTypes.func.isRequired,
139
138
  /** specifies a custom class name. */
140
139
  className: PropTypes.string,
141
- /** specifies a callback function for when the user loses focus in the `SearchField` component. The default is an empty function. For example:
140
+ /** specifies a callback function for when the user loses focus in the `SearchField` component.
141
+ * The default is an empty function. For example:
142
142
  ```jsx
143
143
  <SearchField onBlur={event => console.log(event)} />
144
144
  ``` */
145
145
  onBlur: PropTypes.func,
146
- /** specifies a callback function for when the value in `SearchField` is changed by the user. The default is an empty function. For example:
146
+ /** specifies a callback function for when the value in `SearchField` is changed by the user.
147
+ * The default is an empty function. For example:
147
148
  ```jsx
148
149
  <SearchField onChange={value => console.log(value)} />
149
150
  ``` */
150
151
  onChange: PropTypes.func,
151
- /** specifies a callback function for when the value in `SearchField` is cleared by the user. The default is an empty function. For example:
152
+ /** specifies a callback function for when the value in `SearchField` is cleared by the user.
153
+ * The default is an empty function. For example:
152
154
  ```jsx
153
155
  <SearchField onClear={() => console.log('search cleared')} />
154
156
  ``` */
155
157
  onClear: PropTypes.func,
156
- /** specifies a callback function for when the user focuses in the `SearchField` component. The default is an empty function. For example:
158
+ /** specifies a callback function for when the user focuses in the `SearchField` component.
159
+ * The default is an empty function. For example:
157
160
  ```jsx
158
161
  <SearchField onFocus={event => console.log(event)} />
159
162
  ``` */
160
163
  onFocus: PropTypes.func,
161
- /** specifies the screenreader text for both the clear and submit buttons (e.g., for i18n translations). The default is `{ label: 'search', clearButton: 'clear search', searchButton: 'submit search' }`. */
164
+ /** specifies the screenreader text for both the clear and submit buttons (e.g., for i18n translations).
165
+ * The default is `{ label: 'search', clearButton: 'clear search', searchButton: 'submit search' }`. */
162
166
  screenReaderText: PropTypes.shape({
163
167
  label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
164
168
  submitButton: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
@@ -171,7 +175,8 @@ SearchFieldAdvanced.propTypes = {
171
175
  submit: PropTypes.element.isRequired,
172
176
  clear: PropTypes.element,
173
177
  }),
174
- /** specifies the aria-label attribute on the form element. This is useful if you use the `SearchField` component more than once on a page. */
178
+ /** specifies the aria-label attribute on the form element. This is useful if you use the `SearchField` component
179
+ * more than once on a page. */
175
180
  formAriaLabel: PropTypes.string,
176
181
  /** Specifies whether the `SearchField` is disabled. */
177
182
  disabled: PropTypes.bool,
@@ -1,4 +1,3 @@
1
- /* eslint-disable max-len */
2
1
  import React, { useContext } from 'react';
3
2
  import PropTypes from 'prop-types';
4
3
  import classNames from 'classnames';
@@ -21,8 +20,9 @@ function SearchFieldLabel({ children, ...props }) {
21
20
 
22
21
  SearchFieldLabel.propTypes = {
23
22
  /**
24
- * specifies the label to use for the input field (e.g., for i18n translations). Note: if `children` is not provided,
25
- * a screenreader-only label will be used in its placed based on the `screenReaderText.label` prop for `SearchField.Advanced`.
23
+ * specifies the label to use for the input field (e.g., for i18n translations).
24
+ * Note: if `children` is not provided, a screenreader-only label will be used in
25
+ * its placed based on the `screenReaderText.label` prop for `SearchField.Advanced`.
26
26
  */
27
27
  children: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
28
28
  };
@@ -1,4 +1,3 @@
1
- /* eslint-disable max-len */
2
1
  import React, { useCallback } from 'react';
3
2
  import PropTypes from 'prop-types';
4
3
 
@@ -6,9 +6,9 @@ components:
6
6
  - SelectableBoxSet
7
7
  categories:
8
8
  - Forms
9
- status: 'New'
9
+ status: 'Stable'
10
10
  designStatus: 'Done'
11
- devStatus: 'In progress'
11
+ devStatus: 'Done'
12
12
  notes: |
13
13
  ---
14
14
 
@@ -26,7 +26,7 @@ As ``Checkbox``
26
26
  const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
27
27
  const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
28
28
 
29
- const handleChange = e => {
29
+ const handleChange = (e) => {
30
30
  e.target.checked ? add(e.target.value) : remove(e.target.value);
31
31
  };
32
32
 
@@ -34,35 +34,32 @@ As ``Checkbox``
34
34
  const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
35
35
 
36
36
  return (
37
- <div className="bg-light-200 p-3">
38
- <SelectableBox.Set
39
- value={checkedCheeses}
37
+ <SelectableBox.Set
38
+ className="bg-light-200 p-3"
39
+ value={checkedCheeses}
40
+ type={type}
41
+ onChange={handleChange}
42
+ name="cheeses"
43
+ columns={isExtraSmall ? 1 : 2}
44
+ ariaLabel="cheese selection"
45
+ >
46
+ <SelectableBox value="swiss" type={type} aria-label="swiss checkbox">
47
+ <h3>It is my first SelectableBox</h3>
48
+ <p>Swiss</p>
49
+ </SelectableBox>
50
+ <SelectableBox value="cheddar" inputHidden={false} type={type} aria-label="cheddar checkbox">
51
+ <h3>Cheddar</h3>
52
+ </SelectableBox>
53
+ <SelectableBox
54
+ value="pepperjack"
55
+ inputHidden={false}
40
56
  type={type}
41
- onChange={handleChange}
42
- name="cheeses"
43
- columns={isExtraSmall ? 1 : 2}
44
- ariaLabel="cheese selection"
57
+ isInvalid={isInvalid()}
58
+ aria-label="pepperjack checkbox"
45
59
  >
46
- <SelectableBox value="swiss" type={type} aria-label="swiss checkbox">
47
- <div>
48
- <h3>It is my first SelectableBox</h3>
49
- <p>Swiss</p>
50
- </div>
51
- </SelectableBox>
52
- <SelectableBox value="cheddar" inputHidden={false} type={type} aria-label="cheddar checkbox">
53
- Cheddar
54
- </SelectableBox>
55
- <SelectableBox
56
- value="pepperjack"
57
- inputHidden={false}
58
- type={type}
59
- isInvalid={isInvalid()}
60
- aria-label="pepperjack checkbox"
61
- >
62
- <h3>Pepperjack</h3>
63
- </SelectableBox>
64
- </SelectableBox.Set>
65
- </div>
60
+ <h3>Pepperjack</h3>
61
+ </SelectableBox>
62
+ </SelectableBox.Set>
66
63
  );
67
64
  }
68
65
  ```
@@ -71,31 +68,27 @@ As ``Checkbox``
71
68
 
72
69
  ```jsx live
73
70
  () => {
74
- const type = 'radio';
75
71
  const [value, setValue] = useState('green');
76
- const handleChange = e => setValue(e.target.value);
72
+ const handleChange = (e) => setValue(e.target.value);
77
73
  const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
78
74
 
79
75
  return (
80
76
  <SelectableBox.Set
81
- type={type}
82
77
  value={value}
83
78
  onChange={handleChange}
84
79
  name="colors"
85
80
  columns={isExtraSmall ? 1 : 3}
86
81
  ariaLabel="color selection"
87
82
  >
88
- <SelectableBox value="red" type={type} aria-label="red checkbox">
89
- <div>
90
- <h3>It is Red color</h3>
91
- <p>Select me</p>
92
- </div>
83
+ <SelectableBox value="red" aria-label="red checkbox">
84
+ <h3>It is Red color</h3>
85
+ <p>Select me</p>
93
86
  </SelectableBox>
94
- <SelectableBox value="green" inputHidden={false} type={type} aria-label="green-checkbox">
87
+ <SelectableBox value="green" inputHidden={false} aria-label="green radio-button">
95
88
  <h3>Green</h3>
96
89
  <p>Leaves and grass</p>
97
90
  </SelectableBox>
98
- <SelectableBox value="blue" inputHidden={false} type={type} aria-label="blue checkbox">
91
+ <SelectableBox value="blue" inputHidden={false} aria-label="blue radio-button">
99
92
  <h3>Blue</h3>
100
93
  <p>The sky</p>
101
94
  </SelectableBox>
@@ -103,6 +96,7 @@ As ``Checkbox``
103
96
  );
104
97
  }
105
98
  ```
99
+
106
100
  ## As Checkbox
107
101
  As ``Checkbox`` with ``isIndeterminate``
108
102
 
@@ -117,7 +111,7 @@ As ``Checkbox`` with ``isIndeterminate``
117
111
  const isIndeterminate = someChecked && !allChecked;
118
112
  const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.small.maxWidth });
119
113
 
120
- const handleChange = e => {
114
+ const handleChange = (e) => {
121
115
  e.target.checked ? add(e.target.value) : remove(e.target.value);
122
116
  };
123
117
 
@@ -127,18 +121,17 @@ As ``Checkbox`` with ``isIndeterminate``
127
121
 
128
122
  return (
129
123
  <>
130
- <div className="mb-3">
131
- <SelectableBox
132
- checked={allChecked}
133
- isIndeterminate={isIndeterminate}
134
- onClick={handleCheckAllChange}
135
- inputHidden={false}
136
- type={type}
137
- aria-label="all options checkbox"
138
- >
139
- All the cheese
140
- </SelectableBox>
141
- </div>
124
+ <SelectableBox
125
+ className="mb-3"
126
+ checked={allChecked}
127
+ isIndeterminate={isIndeterminate}
128
+ onClick={handleCheckAllChange}
129
+ inputHidden={false}
130
+ type={type}
131
+ aria-label="all options checkbox"
132
+ >
133
+ All the cheese
134
+ </SelectableBox>
142
135
  <SelectableBox.Set
143
136
  value={checkedCheeses}
144
137
  type={type}
@@ -148,13 +141,11 @@ As ``Checkbox`` with ``isIndeterminate``
148
141
  ariaLabel="cheese selection"
149
142
  >
150
143
  <SelectableBox value="swiss" type={type} aria-label="swiss checkbox">
151
- <div>
152
- <h3>It is my first SelectableBox</h3>
153
- <p>Swiss</p>
154
- </div>
144
+ <h3>It is my first SelectableBox</h3>
145
+ <p>Swiss</p>
155
146
  </SelectableBox>
156
147
  <SelectableBox value="cheddar" inputHidden={false} type={type} aria-label="cheddar checkbox">
157
- Cheddar
148
+ <h3>Cheddar</h3>
158
149
  </SelectableBox>
159
150
  <SelectableBox value="pepperjack" inputHidden={false} type={type} aria-label="pepperjack checkbox">
160
151
  <h3>Pepperjack</h3>
@@ -173,16 +164,16 @@ As ``Checkbox`` with ``ariaLabelledby``
173
164
  const allCheeseOptions = ['swiss', 'cheddar', 'pepperjack'];
174
165
  const [checkedCheeses, { add, remove, set, clear }] = useCheckboxSetValues(['swiss']);
175
166
 
176
- const handleChange = e => {
167
+ const handleChange = (e) => {
177
168
  e.target.checked ? add(e.target.value) : remove(e.target.value);
178
169
  };
179
170
 
180
171
  const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
181
172
 
182
173
  return (
183
- <div className="bg-light-200 p-3">
174
+ <Stack className="bg-light-200 p-3">
184
175
  <h3 id="cheese selection" className="mb-4">
185
- Select your favorite cheese
176
+ Select your favorite cheese:
186
177
  </h3>
187
178
  <SelectableBox.Set
188
179
  value={checkedCheeses}
@@ -193,22 +184,63 @@ As ``Checkbox`` with ``ariaLabelledby``
193
184
  ariaLabelledby="cheese selection"
194
185
  >
195
186
  <SelectableBox value="swiss" inputHidden={false} type={type} aria-label="swiss checkbox">
196
- <h3>
197
- Swiss
198
- </h3>
187
+ <h3>Swiss</h3>
199
188
  </SelectableBox>
200
189
  <SelectableBox value="cheddar" inputHidden={false} type={type} aria-label="cheddar checkbox">
201
- <h3>
202
- Cheddar
203
- </h3>
190
+ <h3>Cheddar</h3>
204
191
  </SelectableBox>
205
192
  <SelectableBox value="pepperjack" inputHidden={false} type={type} aria-label="pepperjack checkbox">
206
- <h3>
207
- Pepperjack
208
- </h3>
193
+ <h3>Pepperjack</h3>
209
194
  </SelectableBox>
210
195
  </SelectableBox.Set>
211
- </div>
196
+ </Stack>
197
+ );
198
+ }
199
+ ```
200
+
201
+ ## Without active outline
202
+ The `showActiveBoxState` property only affects `SelectableBox` that have `inputHidden` set to `false`.
203
+ If a component has no input, the border is always rendered in an active state.
204
+
205
+ ```jsx live
206
+ () => {
207
+ const [value, setValue] = useState('apples');
208
+ const handleChange = (e) => setValue(e.target.value);
209
+ const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
210
+
211
+ return (
212
+ <SelectableBox.Set
213
+ value={value}
214
+ onChange={handleChange}
215
+ name="fruits"
216
+ columns={isExtraSmall ? 1 : 3}
217
+ ariaLabel="fruits selection"
218
+ >
219
+ <SelectableBox
220
+ value="apples"
221
+ inputHidden={false}
222
+ showActiveBoxState={false}
223
+ aria-label="apple radio-button"
224
+ >
225
+ <h3>Apples</h3>
226
+ </SelectableBox>
227
+ <SelectableBox
228
+ value="oranges"
229
+ inputHidden={false}
230
+ showActiveBoxState={false}
231
+ aria-label="orange radio-button"
232
+ >
233
+ <h3>Oranges</h3>
234
+ </SelectableBox>
235
+ <SelectableBox
236
+ value="bananas"
237
+ inputHidden={false}
238
+ showActiveBoxState={false}
239
+ aria-label="banana radio-button"
240
+ >
241
+ <h3>Bananas</h3>
242
+ </SelectableBox>
243
+ </SelectableBox.Set>
212
244
  );
213
245
  }
214
246
  ```
@@ -22,6 +22,7 @@ const SelectableBox = React.forwardRef(({
22
22
  onFocus,
23
23
  inputHidden,
24
24
  className,
25
+ showActiveBoxState,
25
26
  ...props
26
27
  }, ref) => {
27
28
  const inputType = getInputType('SelectableBox', type);
@@ -63,7 +64,7 @@ const SelectableBox = React.forwardRef(({
63
64
  onClick={() => inputRef.current.click()}
64
65
  onFocus={onFocus}
65
66
  className={classNames('pgn__selectable_box', className, {
66
- 'pgn__selectable_box-active': isChecked() || checked,
67
+ 'pgn__selectable_box-active': (!inputHidden && !showActiveBoxState) ? false : isChecked() || checked,
67
68
  'pgn__selectable_box-invalid': isInvalid,
68
69
  })}
69
70
  tabIndex={0}
@@ -97,6 +98,8 @@ SelectableBox.propTypes = {
97
98
  isInvalid: PropTypes.bool,
98
99
  /** A class that is appended to the base element. */
99
100
  className: PropTypes.string,
101
+ /** Controls the visibility of the active state for the `SelectableBox`. */
102
+ showActiveBoxState: PropTypes.bool,
100
103
  };
101
104
 
102
105
  SelectableBox.defaultProps = {
@@ -109,6 +112,7 @@ SelectableBox.defaultProps = {
109
112
  isIndeterminate: false,
110
113
  isInvalid: false,
111
114
  className: undefined,
115
+ showActiveBoxState: true,
112
116
  };
113
117
 
114
118
  SelectableBox.Set = SelectableBoxSet;
@@ -100,6 +100,13 @@ describe('<SelectableBox />', () => {
100
100
  rerender(<SelectableCheckbox inputHidden={false} />);
101
101
  expect(inputElement.getAttribute('hidden')).toBeNull();
102
102
  });
103
+ it('renders with active state and updates to inactive when showActiveBoxState is false', async () => {
104
+ const { rerender } = render(<SelectableCheckbox inputHidden={false} checked />);
105
+ const selectableBox = screen.getByRole('button');
106
+ expect(selectableBox.classList.contains('pgn__selectable_box-active')).toEqual(true);
107
+ rerender(<SelectableCheckbox inputHidden={false} showActiveBoxState={false} checked />);
108
+ expect(selectableBox.classList.contains('pgn__selectable_box-active')).toEqual(false);
109
+ });
103
110
  });
104
111
  describe('correct interactions', () => {
105
112
  it('correct checkbox state change when checked is changed', () => {
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
- import '@testing-library/jest-dom/extend-expect';
3
+ import '@testing-library/jest-dom';
4
4
  import userEvent from '@testing-library/user-event';
5
5
  import SelectableBox from '..';
6
6
 
@@ -223,3 +223,79 @@ devStatus: 'Done'
223
223
  </Tab>
224
224
  </Tabs>
225
225
  ```
226
+
227
+ ## Conditional rendering
228
+
229
+ ```jsx live
230
+ () => {
231
+ const librariesEnabled = true;
232
+ const visibleTabs = useMemo(() => {
233
+ const tabs = [];
234
+
235
+ tabs.push(
236
+ <Tab
237
+ key="courses"
238
+ eventKey="courses"
239
+ title="Courses"
240
+ >
241
+ Hello I am the courses panel.
242
+ </Tab>
243
+ );
244
+
245
+ tabs.push(
246
+ <Tab
247
+ key="programs"
248
+ eventKey="programs"
249
+ title="Programs"
250
+ >
251
+ Hello I am the programs panel.
252
+ </Tab>
253
+ );
254
+
255
+ if (librariesEnabled) {
256
+ tabs.push(
257
+ <Tab
258
+ key="libraries"
259
+ eventKey="libraries"
260
+ title="Libraries"
261
+ >
262
+ Hello I am the libraries panel.
263
+ </Tab>
264
+ );
265
+ }
266
+
267
+ return tabs;
268
+ }, [librariesEnabled]);
269
+
270
+ return (
271
+ <Tabs
272
+ id="tabs"
273
+ defaultActiveKey="courses"
274
+ >
275
+ {visibleTabs}
276
+ </Tabs>
277
+ );
278
+ }
279
+ ```
280
+
281
+ ***
282
+
283
+ ## Tabs.Deprecated
284
+
285
+ <br/>
286
+
287
+ ### (Deprecated) basic usage
288
+
289
+ ```jsx live
290
+ <Tabs.Deprecated
291
+ labels={[
292
+ 'Panel 1',
293
+ 'Panel 2',
294
+ 'Panel 3'
295
+ ]}
296
+ >
297
+ <div>Hello I am the first panel</div>
298
+ <div>Hello I am the second panel</div>
299
+ <div>Hello I am the third panel</div>
300
+ </Tabs.Deprecated>
301
+ ```
@@ -1,4 +1,10 @@
1
- import React, { useEffect, useMemo, useRef } from 'react';
1
+ import React, {
2
+ useEffect,
3
+ useMemo,
4
+ useRef,
5
+ useState,
6
+ useCallback,
7
+ } from 'react';
2
8
  import classNames from 'classnames';
3
9
  import PropTypes from 'prop-types';
4
10
  import BaseTabs from 'react-bootstrap/Tabs';
@@ -17,15 +23,15 @@ function Tabs({
17
23
  activeKey,
18
24
  ...props
19
25
  }) {
20
- const containerElementRef = useRef(null);
26
+ const [containerElementRef, setContainerElementRef] = useState(null);
21
27
  const overflowElementRef = useRef(null);
22
28
  const indexOfLastVisibleChild = useIndexOfLastVisibleChild(
23
- containerElementRef.current?.children[0],
29
+ containerElementRef?.firstChild,
24
30
  overflowElementRef.current?.parentNode,
25
31
  );
26
32
 
27
33
  useEffect(() => {
28
- if (containerElementRef.current) {
34
+ if (containerElementRef) {
29
35
  const observer = new MutationObserver((mutations => {
30
36
  mutations.forEach(mutation => {
31
37
  // React-Bootstrap attribute 'data-rb-event-key' is responsible for the tab identification
@@ -34,8 +40,8 @@ function Tabs({
34
40
  const isActive = mutation.target.getAttribute('aria-selected') === 'true';
35
41
  // datakey attribute is added manually to the dropdown
36
42
  // elements so that they correspond to the native tabs' eventKey
37
- const element = containerElementRef.current.querySelector(`[datakey='${eventKey}']`);
38
- const moreTab = containerElementRef.current.querySelector('.pgn__tab_more');
43
+ const element = containerElementRef.querySelector(`[datakey='${eventKey}']`);
44
+ const moreTab = containerElementRef.querySelector('.pgn__tab_more');
39
45
  if (isActive) {
40
46
  element?.classList.add('active');
41
47
  // Here we add active class to the 'More Tab' if element exists in the dropdown
@@ -49,13 +55,13 @@ function Tabs({
49
55
  }
50
56
  });
51
57
  }));
52
- observer.observe(containerElementRef.current, {
58
+ observer.observe(containerElementRef, {
53
59
  attributes: true, subtree: true, attributeFilter: ['aria-selected'],
54
60
  });
55
61
  return () => observer.disconnect();
56
62
  }
57
63
  return undefined;
58
- }, []);
64
+ }, [containerElementRef]);
59
65
 
60
66
  useEffect(() => {
61
67
  if (overflowElementRef.current?.parentNode) {
@@ -63,10 +69,10 @@ function Tabs({
63
69
  }
64
70
  }, [overflowElementRef.current?.parentNode]);
65
71
 
66
- const handleDropdownTabClick = (eventKey) => {
67
- const hiddenTab = containerElementRef.current.querySelector(`[data-rb-event-key='${eventKey}']`);
72
+ const handleDropdownTabClick = useCallback((eventKey) => {
73
+ const hiddenTab = containerElementRef.querySelector(`[data-rb-event-key='${eventKey}']`);
68
74
  hiddenTab.click();
69
- };
75
+ }, [containerElementRef]);
70
76
 
71
77
  const tabsChildren = useMemo(() => {
72
78
  const indexOfOverflowStart = indexOfLastVisibleChild + 1;
@@ -164,10 +170,10 @@ function Tabs({
164
170
  />
165
171
  ));
166
172
  return childrenList;
167
- }, [activeKey, children, defaultActiveKey, indexOfLastVisibleChild, moreTabText]);
173
+ }, [activeKey, children, defaultActiveKey, indexOfLastVisibleChild, moreTabText, handleDropdownTabClick]);
168
174
 
169
175
  return (
170
- <div ref={containerElementRef}>
176
+ <div ref={setContainerElementRef}>
171
177
  <BaseTabs
172
178
  defaultActiveKey={defaultActiveKey}
173
179
  activeKey={activeKey}
@@ -12,12 +12,12 @@ window.ResizeObserver = window.ResizeObserver
12
12
  }));
13
13
 
14
14
  function TestComponent() {
15
- const containerElementRef = React.useRef(null);
15
+ const [containerElementRef, setContainerElementRef] = React.useState(null);
16
16
  const overflowElementRef = React.useRef(null);
17
- const indexOfLastVisibleChild = useIndexOfLastVisibleChild(containerElementRef.current, overflowElementRef.current);
17
+ const indexOfLastVisibleChild = useIndexOfLastVisibleChild(containerElementRef, overflowElementRef.current);
18
18
 
19
19
  return (
20
- <div ref={containerElementRef} style={{ display: 'flex' }}>
20
+ <div ref={setContainerElementRef} style={{ display: 'flex' }}>
21
21
  <div style={{ width: '250px' }} className="element">Element 1</div>
22
22
  <div style={{ width: '250px' }} className="element">Element 2</div>
23
23
  <div style={{ width: '250px' }} className="element">Element 3</div>