@telus-uds/components-base 0.0.2-prerelease.6 → 1.0.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 (458) hide show
  1. package/.eslintrc.js +9 -0
  2. package/.ultra.cache.json +1 -1
  3. package/CHANGELOG.md +85 -0
  4. package/README.md +4 -2
  5. package/__fixtures__/Accessible.js +33 -0
  6. package/__fixtures__/Accessible.native.js +32 -0
  7. package/__fixtures__/test-utils.js +25 -0
  8. package/__fixtures__/testTheme.js +851 -57
  9. package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
  10. package/__tests__/Button/ButtonBase.test.jsx +2 -31
  11. package/__tests__/Button/ButtonGroup.test.jsx +6 -7
  12. package/__tests__/Checkbox/Checkbox.test.jsx +94 -0
  13. package/__tests__/Checkbox/CheckboxGroup.test.jsx +246 -0
  14. package/__tests__/ExpandCollapse/ExpandCollapse.test.jsx +2 -2
  15. package/__tests__/HorizontalScroll/HorizontalScroll.test.jsx +164 -0
  16. package/__tests__/Icon/Icon.test.jsx +3 -3
  17. package/__tests__/IconButton/IconButton.test.jsx +52 -0
  18. package/__tests__/InputSupports/InputSupports.test.jsx +50 -0
  19. package/__tests__/Link/LinkBase.test.jsx +0 -14
  20. package/__tests__/List/List.test.jsx +60 -0
  21. package/__tests__/Modal/Modal.test.jsx +47 -0
  22. package/__tests__/Notification/Notification.test.jsx +20 -0
  23. package/__tests__/Pagination/Pagination.test.jsx +2 -2
  24. package/__tests__/Progress/Progress.test.jsx +79 -0
  25. package/__tests__/Radio/Radio.test.jsx +87 -0
  26. package/__tests__/Radio/RadioGroup.test.jsx +220 -0
  27. package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
  28. package/__tests__/RadioCard/RadioCardGroup.test.jsx +246 -0
  29. package/__tests__/Search/Search.test.jsx +73 -0
  30. package/__tests__/Select/Select.test.jsx +94 -0
  31. package/__tests__/Skeleton/Skeleton.test.jsx +61 -0
  32. package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
  33. package/__tests__/Tabs/Tabs.test.jsx +40 -0
  34. package/__tests__/Tags/Tags.test.jsx +327 -0
  35. package/__tests__/TextInput/TextArea.test.jsx +35 -0
  36. package/__tests__/TextInput/{TextInput.test.jsx → TextInputBase.test.jsx} +29 -50
  37. package/__tests__/ThemeProvider/ThemeProvider.test.jsx +77 -0
  38. package/__tests__/ThemeProvider/useThemeTokens.test.jsx +9 -5
  39. package/__tests__/ThemeProvider/utils/theme-tokens.test.js +41 -0
  40. package/__tests__/ToggleSwitch/ToggleSwitch.test.jsx +3 -2
  41. package/__tests__/utils/children.test.jsx +128 -0
  42. package/__tests__/utils/input.test.js +59 -1
  43. package/__tests__/utils/semantics.test.jsx +43 -0
  44. package/__tests__/utils/useCopy.test.js +14 -3
  45. package/babel.config.js +20 -0
  46. package/jest.config.js +8 -3
  47. package/lib/A11yInfoProvider/index.js +54 -26
  48. package/lib/A11yText/index.js +45 -17
  49. package/lib/ActivityIndicator/Spinner.js +81 -0
  50. package/lib/ActivityIndicator/Spinner.native.js +129 -91
  51. package/lib/ActivityIndicator/index.js +28 -12
  52. package/lib/ActivityIndicator/shared.js +27 -12
  53. package/lib/BaseProvider/index.js +34 -11
  54. package/lib/Box/Box.js +152 -35
  55. package/lib/Box/index.js +13 -2
  56. package/lib/Button/Button.js +41 -12
  57. package/lib/Button/ButtonBase.js +125 -97
  58. package/lib/Button/ButtonGroup.js +112 -89
  59. package/lib/Button/ButtonLink.js +48 -17
  60. package/lib/Button/index.js +31 -4
  61. package/lib/Button/propTypes.js +32 -9
  62. package/lib/Card/Card.js +38 -41
  63. package/lib/Card/CardBase.js +85 -0
  64. package/lib/Card/PressableCardBase.js +141 -0
  65. package/lib/Card/index.js +40 -2
  66. package/lib/Checkbox/Checkbox.js +355 -0
  67. package/lib/Checkbox/CheckboxGroup.js +241 -0
  68. package/lib/Checkbox/CheckboxInput.js +74 -0
  69. package/lib/Checkbox/CheckboxInput.native.js +14 -0
  70. package/lib/Checkbox/index.js +21 -0
  71. package/lib/Divider/Divider.js +59 -28
  72. package/lib/Divider/index.js +13 -2
  73. package/lib/ExpandCollapse/Accordion.js +26 -7
  74. package/lib/ExpandCollapse/Control.js +60 -31
  75. package/lib/ExpandCollapse/ExpandCollapse.js +50 -28
  76. package/lib/ExpandCollapse/Panel.js +83 -44
  77. package/lib/ExpandCollapse/index.js +25 -7
  78. package/lib/Feedback/Feedback.js +90 -39
  79. package/lib/Feedback/index.js +13 -2
  80. package/lib/Fieldset/Fieldset.js +165 -0
  81. package/lib/Fieldset/FieldsetContainer.js +46 -0
  82. package/lib/Fieldset/FieldsetContainer.native.js +38 -0
  83. package/lib/Fieldset/Legend.js +38 -0
  84. package/lib/Fieldset/Legend.native.js +48 -0
  85. package/lib/Fieldset/cssReset.js +21 -0
  86. package/lib/Fieldset/index.js +13 -0
  87. package/lib/FlexGrid/Col/Col.js +73 -41
  88. package/lib/FlexGrid/Col/index.js +13 -2
  89. package/lib/FlexGrid/FlexGrid.js +99 -49
  90. package/lib/FlexGrid/Row/Row.js +58 -30
  91. package/lib/FlexGrid/Row/index.js +13 -2
  92. package/lib/FlexGrid/helpers/index.js +9 -1
  93. package/lib/FlexGrid/index.js +13 -2
  94. package/lib/FlexGrid/providers/GutterContext.js +15 -3
  95. package/lib/HorizontalScroll/HorizontalScroll.js +200 -0
  96. package/lib/HorizontalScroll/HorizontalScrollButton.js +127 -0
  97. package/lib/HorizontalScroll/ScrollViewEnd.js +66 -0
  98. package/lib/HorizontalScroll/ScrollViewEnd.native.js +41 -0
  99. package/lib/HorizontalScroll/dictionary.js +18 -0
  100. package/lib/HorizontalScroll/index.js +35 -0
  101. package/lib/HorizontalScroll/itemPositions.js +128 -0
  102. package/lib/Icon/Icon.js +62 -50
  103. package/lib/Icon/IconText.js +101 -0
  104. package/lib/Icon/index.js +31 -3
  105. package/lib/IconButton/IconButton.js +140 -0
  106. package/lib/IconButton/index.js +13 -0
  107. package/lib/InputLabel/InputLabel.js +102 -40
  108. package/lib/InputLabel/LabelContent.js +41 -0
  109. package/lib/InputLabel/LabelContent.native.js +32 -6
  110. package/lib/InputLabel/index.js +13 -2
  111. package/lib/InputSupports/InputSupports.js +109 -0
  112. package/lib/InputSupports/index.js +13 -0
  113. package/lib/InputSupports/propTypes.js +66 -0
  114. package/lib/InputSupports/useInputSupports.js +41 -0
  115. package/lib/Link/ChevronLink.js +58 -31
  116. package/lib/Link/InlinePressable.js +56 -0
  117. package/lib/Link/InlinePressable.native.js +102 -0
  118. package/lib/Link/Link.js +39 -15
  119. package/lib/Link/LinkBase.js +126 -150
  120. package/lib/Link/TextButton.js +53 -18
  121. package/lib/Link/index.js +39 -4
  122. package/lib/List/List.js +81 -0
  123. package/lib/List/ListItem.js +245 -0
  124. package/lib/List/index.js +13 -0
  125. package/lib/Modal/Modal.js +231 -0
  126. package/lib/Modal/dictionary.js +16 -0
  127. package/lib/Modal/index.js +13 -0
  128. package/lib/Notification/Notification.js +216 -0
  129. package/lib/Notification/dictionary.js +15 -0
  130. package/lib/Notification/index.js +13 -0
  131. package/lib/Pagination/PageButton.js +58 -48
  132. package/lib/Pagination/Pagination.js +78 -43
  133. package/lib/Pagination/SideButton.js +79 -58
  134. package/lib/Pagination/dictionary.js +9 -2
  135. package/lib/Pagination/index.js +13 -2
  136. package/lib/Pagination/usePagination.js +12 -2
  137. package/lib/Progress/Progress.js +104 -0
  138. package/lib/Progress/ProgressBar.js +157 -0
  139. package/lib/Progress/ProgressBarBackground.js +61 -0
  140. package/lib/Progress/index.js +16 -0
  141. package/lib/Radio/Radio.js +293 -0
  142. package/lib/Radio/RadioButton.js +152 -0
  143. package/lib/Radio/RadioGroup.js +244 -0
  144. package/lib/Radio/RadioInput.js +76 -0
  145. package/lib/Radio/RadioInput.native.js +14 -0
  146. package/lib/Radio/index.js +21 -0
  147. package/lib/RadioCard/RadioCard.js +244 -0
  148. package/lib/RadioCard/RadioCardGroup.js +252 -0
  149. package/lib/RadioCard/index.js +21 -0
  150. package/lib/Search/Search.js +254 -0
  151. package/lib/Search/dictionary.js +19 -0
  152. package/lib/Search/index.js +13 -0
  153. package/lib/Select/Group.js +33 -0
  154. package/lib/Select/Group.native.js +25 -0
  155. package/lib/Select/Item.js +29 -0
  156. package/lib/Select/Item.native.js +19 -0
  157. package/lib/Select/Picker.js +84 -0
  158. package/lib/Select/Picker.native.js +130 -0
  159. package/lib/Select/Select.js +342 -0
  160. package/lib/Select/index.js +19 -0
  161. package/lib/SideNav/Item.js +63 -37
  162. package/lib/SideNav/ItemContent.js +41 -15
  163. package/lib/SideNav/ItemsGroup.js +55 -31
  164. package/lib/SideNav/SideNav.js +100 -73
  165. package/lib/SideNav/index.js +15 -1
  166. package/lib/Skeleton/Skeleton.js +137 -0
  167. package/lib/Skeleton/index.js +13 -0
  168. package/lib/Skeleton/skeleton.constant.js +12 -0
  169. package/lib/Skeleton/skeletonWebAnimation.js +27 -0
  170. package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
  171. package/lib/Spacer/Spacer.js +49 -18
  172. package/lib/Spacer/index.js +13 -2
  173. package/lib/StackView/StackView.js +71 -31
  174. package/lib/StackView/StackWrap.js +43 -13
  175. package/lib/StackView/StackWrap.native.js +13 -2
  176. package/lib/StackView/StackWrapBox.js +76 -29
  177. package/lib/StackView/StackWrapGap.js +56 -26
  178. package/lib/StackView/common.js +23 -6
  179. package/lib/StackView/getStackedContent.js +47 -17
  180. package/lib/StackView/index.js +29 -5
  181. package/lib/StepTracker/Step.js +245 -0
  182. package/lib/StepTracker/StepTracker.js +202 -0
  183. package/lib/StepTracker/dictionary.js +17 -0
  184. package/lib/StepTracker/index.js +13 -0
  185. package/lib/Tabs/Tabs.js +124 -0
  186. package/lib/Tabs/TabsItem.js +238 -0
  187. package/lib/Tabs/index.js +13 -0
  188. package/lib/Tags/Tags.js +266 -0
  189. package/lib/Tags/index.js +13 -0
  190. package/lib/TextInput/TextArea.js +111 -0
  191. package/lib/TextInput/TextInput.js +50 -304
  192. package/lib/TextInput/TextInputBase.js +256 -0
  193. package/lib/TextInput/index.js +23 -2
  194. package/lib/TextInput/propTypes.js +42 -0
  195. package/lib/ThemeProvider/ThemeProvider.js +46 -18
  196. package/lib/ThemeProvider/index.js +61 -6
  197. package/lib/ThemeProvider/useSetTheme.js +19 -5
  198. package/lib/ThemeProvider/useTheme.js +13 -4
  199. package/lib/ThemeProvider/useThemeTokens.js +86 -19
  200. package/lib/ThemeProvider/utils/index.js +31 -2
  201. package/lib/ThemeProvider/utils/styles.js +50 -14
  202. package/lib/ThemeProvider/utils/theme-tokens.js +121 -12
  203. package/lib/ToggleSwitch/ToggleSwitch.js +86 -57
  204. package/lib/ToggleSwitch/index.js +13 -2
  205. package/lib/Tooltip/{Backdrop.web.js → Backdrop.js} +20 -8
  206. package/lib/Tooltip/Backdrop.native.js +39 -15
  207. package/lib/Tooltip/Tooltip.js +117 -74
  208. package/lib/Tooltip/dictionary.js +9 -2
  209. package/lib/Tooltip/getTooltipPosition.js +9 -1
  210. package/lib/Tooltip/index.js +13 -2
  211. package/lib/TooltipButton/TooltipButton.js +57 -38
  212. package/lib/TooltipButton/index.js +13 -2
  213. package/lib/Typography/Typography.js +86 -55
  214. package/lib/Typography/index.js +13 -2
  215. package/lib/ViewportProvider/ViewportProvider.js +34 -13
  216. package/lib/ViewportProvider/index.js +28 -3
  217. package/lib/ViewportProvider/useViewport.js +15 -3
  218. package/lib/ViewportProvider/useViewportListener.js +24 -10
  219. package/lib/index.js +539 -26
  220. package/lib/utils/a11y/index.js +31 -0
  221. package/lib/utils/a11y/semantics.js +173 -0
  222. package/lib/utils/a11y/textSize.js +49 -0
  223. package/lib/utils/animation/index.js +15 -2
  224. package/lib/utils/animation/useVerticalExpandAnimation.js +27 -10
  225. package/lib/utils/children.js +134 -0
  226. package/lib/utils/index.js +163 -7
  227. package/lib/utils/info/index.js +19 -0
  228. package/lib/utils/info/platform/index.js +23 -0
  229. package/lib/utils/info/platform/platform.android.js +8 -0
  230. package/lib/utils/info/platform/platform.ios.js +8 -0
  231. package/lib/utils/info/platform/platform.js +8 -0
  232. package/lib/utils/info/platform/platform.native.js +11 -0
  233. package/lib/utils/info/versions.js +16 -0
  234. package/lib/utils/input.js +53 -25
  235. package/lib/utils/pressability.js +120 -0
  236. package/lib/utils/propTypes.js +338 -132
  237. package/lib/utils/useCopy.js +40 -5
  238. package/lib/utils/useHash.js +52 -0
  239. package/lib/utils/useHash.native.js +15 -0
  240. package/lib/utils/useResponsiveProp.js +21 -9
  241. package/lib/utils/useSpacingScale.js +19 -9
  242. package/lib/utils/useUniqueId.js +12 -3
  243. package/package.json +16 -10
  244. package/release-context.json +4 -4
  245. package/src/A11yText/index.jsx +6 -4
  246. package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +5 -3
  247. package/src/ActivityIndicator/Spinner.native.jsx +5 -3
  248. package/src/Box/Box.jsx +131 -39
  249. package/src/Button/Button.jsx +13 -6
  250. package/src/Button/ButtonBase.jsx +134 -125
  251. package/src/Button/ButtonGroup.jsx +85 -86
  252. package/src/Button/ButtonLink.jsx +22 -7
  253. package/src/Button/propTypes.js +12 -2
  254. package/src/Card/Card.jsx +5 -31
  255. package/src/Card/CardBase.jsx +58 -0
  256. package/src/Card/PressableCardBase.jsx +119 -0
  257. package/src/Card/index.js +3 -0
  258. package/src/Checkbox/Checkbox.jsx +284 -0
  259. package/src/Checkbox/CheckboxGroup.jsx +206 -0
  260. package/src/Checkbox/CheckboxInput.jsx +55 -0
  261. package/src/Checkbox/CheckboxInput.native.jsx +6 -0
  262. package/src/Checkbox/index.js +5 -0
  263. package/src/Divider/Divider.jsx +7 -4
  264. package/src/ExpandCollapse/Accordion.jsx +3 -2
  265. package/src/ExpandCollapse/Control.jsx +40 -43
  266. package/src/ExpandCollapse/ExpandCollapse.jsx +26 -23
  267. package/src/ExpandCollapse/Panel.jsx +69 -63
  268. package/src/Feedback/Feedback.jsx +42 -30
  269. package/src/Fieldset/Fieldset.jsx +136 -0
  270. package/src/Fieldset/FieldsetContainer.jsx +31 -0
  271. package/src/Fieldset/FieldsetContainer.native.jsx +19 -0
  272. package/src/Fieldset/Legend.jsx +21 -0
  273. package/src/Fieldset/Legend.native.jsx +27 -0
  274. package/src/Fieldset/cssReset.js +14 -0
  275. package/src/Fieldset/index.js +3 -0
  276. package/src/FlexGrid/Col/Col.jsx +139 -132
  277. package/src/FlexGrid/FlexGrid.jsx +79 -51
  278. package/src/FlexGrid/Row/Row.jsx +55 -48
  279. package/src/HorizontalScroll/HorizontalScroll.jsx +168 -0
  280. package/src/HorizontalScroll/HorizontalScrollButton.jsx +105 -0
  281. package/src/HorizontalScroll/ScrollViewEnd.jsx +53 -0
  282. package/src/HorizontalScroll/ScrollViewEnd.native.jsx +24 -0
  283. package/src/HorizontalScroll/dictionary.js +11 -0
  284. package/src/HorizontalScroll/index.js +17 -0
  285. package/src/HorizontalScroll/itemPositions.js +101 -0
  286. package/src/Icon/Icon.jsx +46 -49
  287. package/src/Icon/IconText.jsx +68 -0
  288. package/src/Icon/index.js +3 -2
  289. package/src/IconButton/IconButton.jsx +114 -0
  290. package/src/IconButton/index.js +3 -0
  291. package/src/InputLabel/InputLabel.jsx +57 -35
  292. package/src/InputLabel/LabelContent.jsx +21 -0
  293. package/src/InputLabel/LabelContent.native.jsx +11 -2
  294. package/src/InputSupports/InputSupports.jsx +70 -0
  295. package/src/InputSupports/index.js +3 -0
  296. package/src/InputSupports/propTypes.js +44 -0
  297. package/src/InputSupports/useInputSupports.js +30 -0
  298. package/src/Link/ChevronLink.jsx +34 -21
  299. package/src/Link/InlinePressable.jsx +39 -0
  300. package/src/Link/InlinePressable.native.jsx +75 -0
  301. package/src/Link/Link.jsx +23 -13
  302. package/src/Link/LinkBase.jsx +98 -170
  303. package/src/Link/TextButton.jsx +37 -16
  304. package/src/Link/index.js +2 -1
  305. package/src/List/List.jsx +48 -0
  306. package/src/List/ListItem.jsx +182 -0
  307. package/src/List/index.js +3 -0
  308. package/src/Modal/Modal.jsx +190 -0
  309. package/src/Modal/dictionary.js +9 -0
  310. package/src/Modal/index.js +3 -0
  311. package/src/Notification/Notification.jsx +164 -0
  312. package/src/Notification/dictionary.js +8 -0
  313. package/src/Notification/index.js +3 -0
  314. package/src/Pagination/PageButton.jsx +42 -49
  315. package/src/Pagination/Pagination.jsx +88 -92
  316. package/src/Pagination/SideButton.jsx +58 -66
  317. package/src/Progress/Progress.jsx +78 -0
  318. package/src/Progress/ProgressBar.jsx +123 -0
  319. package/src/Progress/ProgressBarBackground.jsx +36 -0
  320. package/src/Progress/index.js +6 -0
  321. package/src/Radio/Radio.jsx +240 -0
  322. package/src/Radio/RadioButton.jsx +142 -0
  323. package/src/Radio/RadioGroup.jsx +209 -0
  324. package/src/Radio/RadioInput.jsx +57 -0
  325. package/src/Radio/RadioInput.native.jsx +6 -0
  326. package/src/Radio/index.js +5 -0
  327. package/src/RadioCard/RadioCard.jsx +198 -0
  328. package/src/RadioCard/RadioCardGroup.jsx +218 -0
  329. package/src/RadioCard/index.js +5 -0
  330. package/src/Search/Search.jsx +225 -0
  331. package/src/Search/dictionary.js +12 -0
  332. package/src/Search/index.js +3 -0
  333. package/src/Select/Group.jsx +15 -0
  334. package/src/Select/Group.native.jsx +14 -0
  335. package/src/Select/Item.jsx +11 -0
  336. package/src/Select/Item.native.jsx +10 -0
  337. package/src/Select/Picker.jsx +74 -0
  338. package/src/Select/Picker.native.jsx +102 -0
  339. package/src/Select/Select.jsx +298 -0
  340. package/src/Select/index.js +8 -0
  341. package/src/SideNav/Item.jsx +54 -47
  342. package/src/SideNav/ItemsGroup.jsx +50 -43
  343. package/src/SideNav/SideNav.jsx +68 -60
  344. package/src/Skeleton/Skeleton.jsx +94 -0
  345. package/src/Skeleton/index.js +3 -0
  346. package/src/Skeleton/skeleton.constant.js +3 -0
  347. package/src/Skeleton/skeletonWebAnimation.js +13 -0
  348. package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
  349. package/src/Spacer/Spacer.jsx +11 -4
  350. package/src/StackView/StackView.jsx +53 -23
  351. package/src/StackView/StackWrap.jsx +16 -7
  352. package/src/StackView/StackWrapBox.jsx +62 -28
  353. package/src/StackView/StackWrapGap.jsx +46 -24
  354. package/src/StackView/common.jsx +3 -2
  355. package/src/StackView/getStackedContent.jsx +8 -2
  356. package/src/StepTracker/Step.jsx +202 -0
  357. package/src/StepTracker/StepTracker.jsx +174 -0
  358. package/src/StepTracker/dictionary.js +10 -0
  359. package/src/StepTracker/index.js +3 -0
  360. package/src/Tabs/Tabs.jsx +97 -0
  361. package/src/Tabs/TabsItem.jsx +212 -0
  362. package/src/Tabs/index.js +3 -0
  363. package/src/Tags/Tags.jsx +219 -0
  364. package/src/Tags/index.js +3 -0
  365. package/src/TextInput/TextArea.jsx +79 -0
  366. package/src/TextInput/TextInput.jsx +18 -284
  367. package/src/TextInput/TextInputBase.jsx +217 -0
  368. package/src/TextInput/index.js +2 -1
  369. package/src/TextInput/propTypes.js +29 -0
  370. package/src/ThemeProvider/ThemeProvider.jsx +11 -7
  371. package/src/ThemeProvider/useSetTheme.js +4 -0
  372. package/src/ThemeProvider/useThemeTokens.js +56 -5
  373. package/src/ThemeProvider/utils/styles.js +18 -5
  374. package/src/ThemeProvider/utils/theme-tokens.js +74 -5
  375. package/src/ToggleSwitch/ToggleSwitch.jsx +51 -53
  376. package/src/Tooltip/{Backdrop.web.jsx → Backdrop.jsx} +0 -0
  377. package/src/Tooltip/Tooltip.jsx +135 -131
  378. package/src/TooltipButton/TooltipButton.jsx +23 -27
  379. package/src/Typography/Typography.jsx +72 -59
  380. package/src/index.js +31 -3
  381. package/src/utils/a11y/index.js +2 -0
  382. package/src/utils/a11y/semantics.js +162 -0
  383. package/src/utils/a11y/textSize.js +30 -0
  384. package/src/utils/children.jsx +119 -0
  385. package/src/utils/index.js +6 -0
  386. package/src/utils/info/index.js +8 -0
  387. package/src/utils/info/platform/index.js +11 -0
  388. package/src/utils/info/platform/platform.android.js +1 -0
  389. package/src/utils/info/platform/platform.ios.js +1 -0
  390. package/src/utils/info/platform/platform.js +1 -0
  391. package/src/utils/info/platform/platform.native.js +4 -0
  392. package/src/utils/info/versions.js +6 -0
  393. package/src/utils/input.js +36 -25
  394. package/src/utils/pressability.js +96 -0
  395. package/src/utils/propTypes.js +291 -90
  396. package/src/utils/useCopy.js +30 -4
  397. package/src/utils/useHash.js +39 -0
  398. package/src/utils/useHash.native.js +6 -0
  399. package/stories/A11yText/A11yText.stories.jsx +6 -10
  400. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +1 -1
  401. package/stories/Box/Box.stories.jsx +1 -1
  402. package/stories/Button/Button.stories.jsx +7 -2
  403. package/stories/Button/ButtonGroup.stories.jsx +1 -1
  404. package/stories/Button/ButtonLink.stories.jsx +1 -1
  405. package/stories/Card/Card.stories.jsx +1 -1
  406. package/stories/Checkbox/Checkbox.stories.jsx +94 -0
  407. package/stories/Divider/Divider.stories.jsx +1 -1
  408. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +2 -2
  409. package/stories/Feedback/Feedback.stories.jsx +5 -6
  410. package/stories/FlexGrid/01 FlexGrid.stories.jsx +1 -1
  411. package/stories/FlexGrid/02 Row.stories.jsx +1 -1
  412. package/stories/FlexGrid/03 Col.stories.jsx +1 -1
  413. package/stories/Icon/Icon.stories.jsx +27 -7
  414. package/stories/IconButton/IconButton.stories.jsx +50 -0
  415. package/stories/InputLabel/InputLabel.stories.jsx +1 -1
  416. package/stories/Link/ChevronLink.stories.jsx +1 -1
  417. package/stories/Link/Link.stories.jsx +28 -18
  418. package/stories/Link/TextButton.stories.jsx +1 -1
  419. package/stories/List/List.stories.jsx +117 -0
  420. package/stories/Modal/Modal.stories.jsx +29 -0
  421. package/stories/Notification/Notification.stories.jsx +82 -0
  422. package/stories/Pagination/Pagination.stories.jsx +1 -1
  423. package/stories/Progress/Progress.stories.jsx +93 -0
  424. package/stories/Radio/Radio.stories.jsx +100 -0
  425. package/stories/RadioCard/RadioCard.stories.jsx +98 -0
  426. package/stories/Search/Search.stories.jsx +16 -0
  427. package/stories/Select/Select.stories.jsx +55 -0
  428. package/stories/SideNav/SideNav.stories.jsx +1 -1
  429. package/stories/SideNav/SideNavItem.stories.jsx +1 -1
  430. package/stories/SideNav/SideNavItemsGroup.stories.jsx +1 -1
  431. package/stories/Skeleton/Skeleton.stories.jsx +36 -0
  432. package/stories/Spacer/Spacer.stories.jsx +1 -1
  433. package/stories/StackView/StackView.stories.jsx +1 -1
  434. package/stories/StackView/StackWrap.stories.jsx +1 -1
  435. package/stories/StepTracker/StepTracker.stories.jsx +71 -0
  436. package/stories/Tabs/Tabs.stories.jsx +97 -0
  437. package/stories/Tags/Tags.stories.jsx +69 -0
  438. package/stories/TextInput/TextArea.stories.jsx +100 -0
  439. package/stories/TextInput/TextInput.stories.jsx +1 -1
  440. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +1 -1
  441. package/stories/Tooltip/Tooltip.stories.jsx +1 -1
  442. package/stories/TooltipButton/TooltipButton.stories.jsx +1 -1
  443. package/stories/Typography/Typography.stories.jsx +1 -1
  444. package/stories/{platform-supports.web.jsx → platform-supports.jsx} +1 -1
  445. package/stories/supports.jsx +38 -4
  446. package/__fixtures__/accessible.icon.svg +0 -6
  447. package/babel.config.json +0 -8
  448. package/docs/Contributing.stories.mdx +0 -9
  449. package/docs/Fonts.stories.mdx +0 -104
  450. package/docs/Icons.stories.mdx +0 -144
  451. package/docs/Introduction.stories.mdx +0 -9
  452. package/lib/ActivityIndicator/Spinner.web.js +0 -55
  453. package/lib/InputLabel/LabelContent.web.js +0 -17
  454. package/lib/config/svgr-icons-web.js +0 -9
  455. package/lib/config/svgr-icons.js +0 -52
  456. package/src/InputLabel/LabelContent.web.jsx +0 -13
  457. package/src/config/svgr-icons-web.js +0 -11
  458. package/src/config/svgr-icons.js +0 -46
@@ -4,7 +4,7 @@ import Theme from '../../__fixtures__/Theme'
4
4
  import ActivityIndicator from '../../src/ActivityIndicator'
5
5
 
6
6
  // Used to remove the "Animated: `useNativeDriver` is not supported because the native animated module is missing." warnings
7
- jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper')
7
+ jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
8
8
 
9
9
  const render = (jsx) => baseRender(jsx, { wrapper: Theme })
10
10
 
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-console */
2
1
  import React from 'react'
3
2
  import { render } from '@testing-library/react-native'
4
3
  import { Platform, Text } from 'react-native'
@@ -9,41 +8,13 @@ import ButtonBase from '../../src/Button/ButtonBase'
9
8
 
10
9
  beforeEach(() => jest.clearAllMocks())
11
10
 
12
- describe('ButtonBase', () => {
13
- it('throws if both href and onPress are provided', async () => {
14
- jest.spyOn(console, 'error').mockImplementation()
15
- expect(() =>
16
- render(
17
- <Theme>
18
- <ButtonBase href="example.com" onPress={jest.fn()}>
19
- click me
20
- </ButtonBase>
21
- </Theme>
22
- )
23
- ).toThrow()
24
- expect(console.error).toHaveBeenCalledTimes(1)
25
- })
26
-
27
- it('throws if neither href nor onPress are provided', async () => {
28
- jest.spyOn(console, 'error').mockImplementation()
29
- expect(() =>
30
- render(
31
- <Theme>
32
- <ButtonBase>click me</ButtonBase>
33
- </Theme>
34
- )
35
- ).toThrow()
36
- expect(console.error).toHaveBeenCalledTimes(1)
37
- })
38
- })
39
-
40
11
  describe('ButtonBase with render function child', () => {
41
- it('receives text styles in render function from button theme', () => {
12
+ it('receives tokens in render function child', () => {
42
13
  const { tokens } = testTheme.components.Button
43
14
  const arbitraryWeight = '300'
44
15
  const { getByText } = render(
45
16
  <Theme>
46
- <ButtonBase onPress={() => {}} tokens={{ fontWeight: arbitraryWeight }}>
17
+ <ButtonBase onPress={() => {}} tokens={{ ...tokens, fontWeight: arbitraryWeight }}>
47
18
  {({ textStyles }) => <Text style={textStyles}>Function child</Text>}
48
19
  </ButtonBase>
49
20
  </Theme>
@@ -106,7 +106,7 @@ describe('ButtonGroup (uncontrolled)', () => {
106
106
  </Theme>
107
107
  )
108
108
  expect(queryAllByA11yRole('checkbox')).toHaveLength(0)
109
- expect(queryAllByA11yRole('radioGroup')).toHaveLength(1)
109
+ expect(queryAllByA11yRole('radiogroup')).toHaveLength(1)
110
110
  const radios = queryAllByA11yRole('radio')
111
111
  expect(radios).toHaveLength(4)
112
112
 
@@ -158,7 +158,7 @@ describe('ButtonGroup (uncontrolled)', () => {
158
158
  </Theme>
159
159
  )
160
160
 
161
- expect(queryAllByA11yRole('radioGroup')).toHaveLength(0)
161
+ expect(queryAllByA11yRole('radiogroup')).toHaveLength(0)
162
162
  expect(queryAllByA11yRole('radio')).toHaveLength(0)
163
163
 
164
164
  const checks = queryAllByA11yRole('checkbox')
@@ -253,15 +253,14 @@ describe('ButtonGroup (controlled)', () => {
253
253
  expect(handleChange).toHaveBeenCalledTimes(0)
254
254
 
255
255
  const one = getByText('One')
256
- await fireEvent.press(one)
256
+ await fireEvent(one, 'press', { nativeEvent: 'example' })
257
257
  expect(handleChange).toHaveBeenCalledTimes(1)
258
-
259
- expect(handleChange.mock.calls[0][0]).toEqual(['one'])
258
+ expect(handleChange).toHaveBeenLastCalledWith(['one'], { nativeEvent: 'example' })
260
259
 
261
260
  const two = getByText('Two')
262
- await fireEvent.press(two)
261
+ await fireEvent(two, 'press', { nativeEvent: 'example2' })
263
262
  expect(handleChange).toHaveBeenCalledTimes(2)
264
- expect(handleChange.mock.calls[1][0]).toEqual(['two'])
263
+ expect(handleChange).toHaveBeenLastCalledWith(['two'], { nativeEvent: 'example2' })
265
264
  })
266
265
 
267
266
  it("Doesn't change its own selection if `values` is passed", async () => {
@@ -0,0 +1,94 @@
1
+ import React from 'react'
2
+ import { fireEvent, render } from '@testing-library/react-native'
3
+
4
+ import { Checkbox } from '../../src'
5
+ import Theme from '../../__fixtures__/Theme'
6
+
7
+ const checkedId = 'Checkbox-Icon'
8
+ const inputId = 'Checkbox-Input'
9
+ const setup = (props) =>
10
+ render(
11
+ <Theme>
12
+ <Checkbox {...props} />
13
+ </Theme>
14
+ )
15
+
16
+ describe('Checkbox', () => {
17
+ it('renders with defaults', () => {
18
+ const { getByRole } = setup()
19
+
20
+ expect(getByRole('checkbox')).toBeTruthy()
21
+ })
22
+
23
+ it('renders the label', () => {
24
+ const label = 'Test label message'
25
+ const { queryByText } = setup({ label })
26
+
27
+ expect(queryByText(label)).toBeTruthy()
28
+ })
29
+
30
+ it('renders the feedback', () => {
31
+ const feedback = 'Test feedback message'
32
+ const { queryByText } = setup({ feedback })
33
+
34
+ expect(queryByText(feedback)).toBeTruthy()
35
+ })
36
+
37
+ it('renders error styling on validation failure', () => {
38
+ const errorBorderColor = '#e12339' // from __fixtures__/testTheme.js
39
+ const { getByTestId } = setup({ error: true })
40
+
41
+ const checkboxInput = getByTestId(inputId)
42
+ expect(checkboxInput).toHaveStyle({ borderColor: errorBorderColor })
43
+ })
44
+
45
+ it('triggers the callback', () => {
46
+ const onChange = jest.fn()
47
+
48
+ const { getByRole } = setup({ onChange })
49
+
50
+ const checkbox = getByRole('checkbox')
51
+ expect(onChange).not.toHaveBeenCalled()
52
+ fireEvent(checkbox, 'press')
53
+ expect(onChange).toHaveBeenCalledTimes(1)
54
+ })
55
+
56
+ it('cannot be changed if inactive', () => {
57
+ const { getByRole, queryByTestId } = setup({ inactive: true })
58
+
59
+ const checkbox = getByRole('checkbox')
60
+ expect(queryByTestId(checkedId)).toBeFalsy()
61
+ fireEvent(checkbox, 'press')
62
+ expect(queryByTestId(checkedId)).toBeFalsy()
63
+ })
64
+
65
+ describe('when uncontrolled', () => {
66
+ it('uses `defaultChecked` as the initial value', () => {
67
+ const { queryByTestId } = setup({ defaultChecked: true })
68
+
69
+ expect(queryByTestId(checkedId)).toBeTruthy()
70
+ })
71
+
72
+ it('changes value', () => {
73
+ const { getByRole, queryByTestId } = setup({ defaultChecked: false })
74
+
75
+ const checkbox = getByRole('checkbox')
76
+ expect(queryByTestId(checkedId)).toBeFalsy()
77
+ fireEvent(checkbox, 'press')
78
+ expect(queryByTestId(checkedId)).toBeTruthy()
79
+ })
80
+ })
81
+
82
+ describe('when controlled', () => {
83
+ it('calls `onChange` with the new value', () => {
84
+ const onChange = jest.fn()
85
+ const { getByRole, queryByTestId } = setup({ onChange, checked: false })
86
+
87
+ const checkbox = getByRole('checkbox')
88
+ expect(queryByTestId(checkedId)).toBeFalsy()
89
+ fireEvent(checkbox, 'press', { nativeEvent: 'example' })
90
+ expect(onChange).toHaveBeenCalledTimes(1)
91
+ expect(onChange).toHaveBeenCalledWith(true, { nativeEvent: 'example' })
92
+ })
93
+ })
94
+ })
@@ -0,0 +1,246 @@
1
+ import React from 'react'
2
+ import { render, fireEvent } from '@testing-library/react-native'
3
+ import { toHaveTextContent } from '@testing-library/jest-native'
4
+
5
+ import Theme from '../../__fixtures__/Theme'
6
+ import CheckboxGroup from '../../src/Checkbox/CheckboxGroup'
7
+
8
+ const items = [
9
+ { label: 'One', id: 'one' },
10
+ { label: 'Two', id: 'two' },
11
+ { label: 'Three', id: 'three' },
12
+ { label: 'Four', id: 'four' }
13
+ ]
14
+ const checked = { checked: true }
15
+
16
+ // expect().toHaveTextContent doesn't work on arrays, expect().toContain etc doesn't match elements
17
+ const containsText = (queryResult, text) =>
18
+ queryResult.some((testInstance) => toHaveTextContent(testInstance, text).pass)
19
+
20
+ describe('CheckboxGroup', () => {
21
+ // eslint-disable-next-line no-console
22
+ const consoleError = console.error
23
+ beforeEach(() => {
24
+ // eslint-disable-next-line no-console
25
+ console.error = () => {}
26
+ })
27
+ afterEach(() => {
28
+ // eslint-disable-next-line no-console
29
+ console.error = consoleError
30
+ })
31
+
32
+ it('Throws if has `checkedIds` without `onChange`', () => {
33
+ expect(() =>
34
+ render(
35
+ <Theme>
36
+ <CheckboxGroup items={items} checkedIds={['one']} />
37
+ </Theme>
38
+ )
39
+ ).toThrow(/values.+without.+onChange/)
40
+ })
41
+ it("Doesn't throw if has `checkedIds` without `onChange` and is read only", () => {
42
+ expect(() =>
43
+ render(
44
+ <Theme>
45
+ <CheckboxGroup items={items} checkedIds={['one']} readOnly />
46
+ </Theme>
47
+ )
48
+ ).not.toThrow()
49
+ })
50
+ it('Throws if has both `checkedIds` and `initialCheckedIds`', () => {
51
+ expect(() =>
52
+ render(
53
+ <Theme>
54
+ <CheckboxGroup
55
+ items={items}
56
+ checkedIds={['one']}
57
+ initialCheckedIds={['one']}
58
+ onChange={() => {}}
59
+ />
60
+ </Theme>
61
+ )
62
+ ).toThrow(/both(?=.*initialValues)(?=.*values){2}/)
63
+ })
64
+ })
65
+
66
+ describe('CheckboxGroup (uncontrolled)', () => {
67
+ it('Selects unlimited items', async () => {
68
+ const { getByText, queryAllByA11yState } = render(
69
+ <Theme>
70
+ <CheckboxGroup items={items} />
71
+ </Theme>
72
+ )
73
+
74
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
75
+
76
+ const one = getByText('One')
77
+ await fireEvent.press(one)
78
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
79
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
80
+
81
+ const two = getByText('Two')
82
+ await fireEvent.press(two)
83
+ expect(queryAllByA11yState(checked)).toHaveLength(2)
84
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
85
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
86
+
87
+ const three = getByText('Three')
88
+ await fireEvent.press(three)
89
+ expect(queryAllByA11yState(checked)).toHaveLength(3)
90
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
91
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
92
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
93
+
94
+ const four = getByText('Four')
95
+ await fireEvent.press(four)
96
+ expect(queryAllByA11yState(checked)).toHaveLength(4)
97
+ expect(containsText(queryAllByA11yState(checked), 'Four')).toBeTruthy()
98
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
99
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
100
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
101
+ })
102
+
103
+ it('Deselects if the selected item is pressed', async () => {
104
+ const { getByText, queryAllByA11yState } = render(
105
+ <Theme>
106
+ <CheckboxGroup items={items} />
107
+ </Theme>
108
+ )
109
+
110
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
111
+
112
+ const three = getByText('Three')
113
+ await fireEvent.press(three)
114
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
115
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
116
+
117
+ await fireEvent.press(three)
118
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
119
+ expect(containsText(queryAllByA11yState(checked), 'Three')).not.toBeTruthy()
120
+ })
121
+
122
+ it('Is accessible as checkboxes button', async () => {
123
+ const { queryAllByA11yRole, queryAllByA11yState } = render(
124
+ <Theme>
125
+ <CheckboxGroup items={items} />
126
+ </Theme>
127
+ )
128
+
129
+ expect(queryAllByA11yRole('radiogroup')).toHaveLength(0)
130
+ expect(queryAllByA11yRole('radio')).toHaveLength(0)
131
+
132
+ const checks = queryAllByA11yRole('checkbox')
133
+ expect(checks).toHaveLength(4)
134
+
135
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
136
+ await fireEvent.press(checks[0])
137
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
138
+ })
139
+
140
+ it('Auto-selects any provided initialCheckedIds', async () => {
141
+ const { getByText, queryAllByA11yState } = render(
142
+ <Theme>
143
+ <CheckboxGroup items={items} initialCheckedIds={['one', 'two']} />
144
+ </Theme>
145
+ )
146
+ expect(queryAllByA11yState(checked)).toHaveLength(2)
147
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
148
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
149
+
150
+ const three = getByText('Three')
151
+ await fireEvent.press(three)
152
+
153
+ expect(queryAllByA11yState(checked)).toHaveLength(3)
154
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
155
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
156
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
157
+ })
158
+ })
159
+
160
+ describe('CheckboxGroup (controlled)', () => {
161
+ it('Calls onChange handler on press in controlled mode, providing pressed id', async () => {
162
+ const handleChange = jest.fn((arg) => arg)
163
+ const { getByText } = render(
164
+ <Theme>
165
+ <CheckboxGroup items={items} checkedIds={[]} onChange={handleChange} />
166
+ </Theme>
167
+ )
168
+
169
+ expect(handleChange).toHaveBeenCalledTimes(0)
170
+
171
+ const one = getByText('One')
172
+ await fireEvent(one, 'press', { nativeEvent: 'example' })
173
+ expect(handleChange).toHaveBeenCalledTimes(1)
174
+ expect(handleChange).toHaveBeenLastCalledWith(['one'], { nativeEvent: 'example' })
175
+
176
+ const two = getByText('Two')
177
+ await fireEvent(two, 'press', { nativeEvent: 'example2' })
178
+ expect(handleChange).toHaveBeenCalledTimes(2)
179
+ expect(handleChange).toHaveBeenLastCalledWith(['two'], { nativeEvent: 'example2' })
180
+ })
181
+
182
+ it("Doesn't change its own selection if `checkedIds` is passed", async () => {
183
+ const { getByText, queryAllByA11yState } = render(
184
+ <Theme>
185
+ <CheckboxGroup items={items} checkedIds={['one']} onChange={() => {}} />
186
+ </Theme>
187
+ )
188
+
189
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
190
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
191
+
192
+ const one = getByText('One')
193
+ await fireEvent.press(one)
194
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
195
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
196
+
197
+ const two = getByText('Two')
198
+ await fireEvent.press(two)
199
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
200
+ expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
201
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
202
+ })
203
+ })
204
+
205
+ describe('CheckboxGroup (read-only)', () => {
206
+ it("Doesn't call onChange handler when read-only", async () => {
207
+ const handleChange = jest.fn((arg) => arg)
208
+ const { getByText } = render(
209
+ <Theme>
210
+ <CheckboxGroup items={items} checkedIds={[]} onChange={handleChange} readOnly />
211
+ </Theme>
212
+ )
213
+
214
+ expect(handleChange).toHaveBeenCalledTimes(0)
215
+
216
+ const one = getByText('One')
217
+ await fireEvent.press(one)
218
+ expect(handleChange).toHaveBeenCalledTimes(0)
219
+
220
+ const two = getByText('Two')
221
+ await fireEvent.press(two)
222
+ expect(handleChange).toHaveBeenCalledTimes(0)
223
+ })
224
+
225
+ it("Doesn't change its selection on press", async () => {
226
+ const { getByText, queryAllByA11yState } = render(
227
+ <Theme>
228
+ <CheckboxGroup items={items} checkedIds={['one']} readOnly />
229
+ </Theme>
230
+ )
231
+
232
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
233
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
234
+
235
+ const one = getByText('One')
236
+ await fireEvent.press(one)
237
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
238
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
239
+
240
+ const two = getByText('Two')
241
+ await fireEvent.press(two)
242
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
243
+ expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
244
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
245
+ })
246
+ })
@@ -64,10 +64,10 @@ describe('ExpandCollapse', () => {
64
64
  expect(onPress).toHaveBeenCalledTimes(0)
65
65
  expect(queryAllByA11yState({ expanded: true }).length).toBe(0)
66
66
 
67
- await fireEvent.press(getByText('First control'))
67
+ await fireEvent(getByText('First control'), 'press', { nativeEvent: 'example' })
68
68
  expect(queryAllByA11yState({ expanded: true }).length).toBe(1)
69
69
  expect(onPress).toHaveBeenCalledTimes(1)
70
- expect(onPress).toHaveBeenLastCalledWith(panelId)
70
+ expect(onPress).toHaveBeenLastCalledWith(panelId, { nativeEvent: 'example' })
71
71
  })
72
72
  })
73
73
 
@@ -0,0 +1,164 @@
1
+ import React, { useState } from 'react'
2
+ import { Pressable, Text, View } from 'react-native'
3
+ import { fireEvent, render } from '@testing-library/react-native'
4
+ import {
5
+ getItemPositionLayoutHandler,
6
+ getItemPositionScrollTarget,
7
+ useItemPositions
8
+ } from '../../src/HorizontalScroll/itemPositions'
9
+
10
+ // ScrollViewRef.scrollTo doesn't work in Jest - unit-test the utilities instead
11
+ describe('HorizontalScroll', () => {
12
+ describe('getItemPositionScrollTarget', () => {
13
+ const positionsWithoutSpacing = {
14
+ 0: { start: 0, end: 100 },
15
+ 1: { start: 100, end: 200 },
16
+ 2: { start: 200, end: 300 }
17
+ }
18
+ const positions = {
19
+ 0: { start: 0, end: 50 },
20
+ 1: { start: 100, end: 150 },
21
+ 2: { start: 200, end: 250 }
22
+ }
23
+ it('scrolls to the start of an item rather than chopping it', () => {
24
+ const x = getItemPositionScrollTarget(150, 300, positionsWithoutSpacing)
25
+ expect(x).toBe(100)
26
+ })
27
+ it('offsets the position by a button clearance', () => {
28
+ const x = getItemPositionScrollTarget(150, 300, positionsWithoutSpacing, 20)
29
+ expect(x).toBe(80)
30
+ })
31
+ it('scrolls exactly if landing on a gap', () => {
32
+ const x = getItemPositionScrollTarget(170, 300, positions)
33
+ expect(x).toBe(170)
34
+ })
35
+ it('applies button clearance if landing on a gap', () => {
36
+ const x = getItemPositionScrollTarget(170, 300, positions, 40)
37
+ expect(x).toBe(130)
38
+ })
39
+ it('does not apply button clearance on reaching the end', () => {
40
+ const x = getItemPositionScrollTarget(300, 300, positions, 40)
41
+ expect(x).toBe(300)
42
+ })
43
+ it('does not exceed the maximum', () => {
44
+ const x = getItemPositionScrollTarget(320, 300, positions, 40)
45
+ expect(x).toBe(300)
46
+ })
47
+ it('does not go below 0', () => {
48
+ const x = getItemPositionScrollTarget(-420, 300, positions, 40)
49
+ expect(x).toBe(0)
50
+ })
51
+ })
52
+
53
+ // onLayout also doesn't work naturally in jest
54
+ describe('getItemPositionLayoutHandler', () => {
55
+ // Test component using useItemPositions with getItemPositionLayoutHandler
56
+ // that can be rerendered manually and that outputs itemPositions value
57
+ const MockComponent = () => {
58
+ const [num, setNum] = useState()
59
+ const [{ positions }] = useItemPositions()
60
+ return (
61
+ <View>
62
+ <View testID="onlayout[0]" onLayout={getItemPositionLayoutHandler(positions, 0)} />
63
+ <View testID="onlayout[1]" onLayout={getItemPositionLayoutHandler(positions, 1)} />
64
+ <Text testID="output">{JSON.stringify(positions)}</Text>
65
+ <Pressable testID="rerender" onPress={() => setNum(num + 1)}>
66
+ <Text>{num}</Text>
67
+ </Pressable>
68
+ </View>
69
+ )
70
+ }
71
+ it('gets width and x positions from onLayout events', async () => {
72
+ const { getByTestId } = render(<MockComponent />)
73
+
74
+ // onLayout doesn't work in jest but can be called directly as an event, but we
75
+ // have to pass the event object. Can't test that it gets them correctly from style
76
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
77
+ nativeEvent: {
78
+ layout: {
79
+ width: 200,
80
+ x: 0
81
+ }
82
+ }
83
+ })
84
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
85
+ nativeEvent: {
86
+ layout: {
87
+ width: 100,
88
+ x: 250
89
+ }
90
+ }
91
+ })
92
+ await fireEvent.press(getByTestId('rerender'))
93
+ expect(getByTestId('output')).toHaveTextContent(
94
+ '{"0":{"start":0,"end":200},"1":{"start":250,"end":350}}'
95
+ )
96
+ })
97
+ it('does not cause a rerender from onLayout events alone', async () => {
98
+ const { getByTestId } = render(<MockComponent />)
99
+
100
+ expect(getByTestId('output')).toHaveTextContent('{}')
101
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
102
+ nativeEvent: {
103
+ layout: {
104
+ width: 200,
105
+ x: 0
106
+ }
107
+ }
108
+ })
109
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
110
+ nativeEvent: {
111
+ layout: {
112
+ width: 100,
113
+ x: 250
114
+ }
115
+ }
116
+ })
117
+ expect(getByTestId('output')).toHaveTextContent('{}')
118
+ })
119
+ })
120
+
121
+ describe('useItemPositions', () => {
122
+ // Again we're limited in what we can test; we can't test natural onLayout
123
+ // or page load timing, but we can affirm that calling `setIsReady` after layout
124
+ // events causes a re-render that can access positions data
125
+ const IsReadyMockComponent = () => {
126
+ const [{ positions, setIsReady }] = useItemPositions()
127
+ return (
128
+ <View testID="container" onLayout={setIsReady}>
129
+ <View testID="onlayout[0]" onLayout={getItemPositionLayoutHandler(positions, 0)} />
130
+ <View testID="onlayout[1]" onLayout={getItemPositionLayoutHandler(positions, 1)} />
131
+ <Text testID="output">{JSON.stringify(positions)}</Text>
132
+ </View>
133
+ )
134
+ }
135
+ it('causes a rerender when setIsReady is called', async () => {
136
+ const { getByTestId } = render(<IsReadyMockComponent />)
137
+
138
+ expect(getByTestId('output')).toHaveTextContent('{}')
139
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
140
+ nativeEvent: {
141
+ layout: {
142
+ width: 200,
143
+ x: 0
144
+ }
145
+ }
146
+ })
147
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
148
+ nativeEvent: {
149
+ layout: {
150
+ width: 100,
151
+ x: 250
152
+ }
153
+ }
154
+ })
155
+ await fireEvent(getByTestId('container'), 'layout', {
156
+ nativeEvent: { layout: {} }
157
+ })
158
+
159
+ expect(getByTestId('output')).toHaveTextContent(
160
+ '{"0":{"start":0,"end":200},"1":{"start":250,"end":350}}'
161
+ )
162
+ })
163
+ })
164
+ })
@@ -16,7 +16,7 @@ describe('Icon', () => {
16
16
  it('gets default styles from theme', () => {
17
17
  const { getByTestId } = render(
18
18
  <Theme>
19
- <Icon IconSvg={InnerComponent} />
19
+ <Icon icon={InnerComponent} />
20
20
  </Theme>
21
21
  )
22
22
 
@@ -29,7 +29,7 @@ describe('Icon', () => {
29
29
  it('gets styles from variant', () => {
30
30
  const { getByTestId } = render(
31
31
  <Theme>
32
- <Icon IconSvg={InnerComponent} variant={{ size: 'small' }} />
32
+ <Icon icon={InnerComponent} variant={{ size: 'small' }} />
33
33
  </Theme>
34
34
  )
35
35
 
@@ -46,7 +46,7 @@ describe('Icon', () => {
46
46
  const props = { tokens: { size: 30 } }
47
47
  const { getByTestId } = render(
48
48
  <Theme>
49
- <Icon IconSvg={InnerComponent} {...props} />
49
+ <Icon icon={InnerComponent} {...props} />
50
50
  </Theme>
51
51
  )
52
52