@telus-uds/components-base 0.0.2-prerelease.7 → 0.0.2-prerelease.8

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 (349) hide show
  1. package/.ultra.cache.json +1 -1
  2. package/CHANGELOG.md +27 -0
  3. package/__fixtures__/Accessible.js +33 -0
  4. package/__fixtures__/Accessible.native.js +32 -0
  5. package/__fixtures__/testTheme.js +429 -29
  6. package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
  7. package/__tests__/Button/ButtonGroup.test.jsx +2 -2
  8. package/__tests__/Checkbox/CheckboxGroup.test.jsx +247 -0
  9. package/__tests__/Icon/Icon.test.jsx +3 -3
  10. package/__tests__/Modal/Modal.test.jsx +47 -0
  11. package/__tests__/Notification/Notification.test.jsx +20 -0
  12. package/__tests__/Pagination/Pagination.test.jsx +2 -2
  13. package/__tests__/Progress/Progress.test.jsx +79 -0
  14. package/__tests__/Radio/RadioGroup.test.jsx +221 -0
  15. package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
  16. package/__tests__/RadioCard/RadioCardGroup.test.jsx +247 -0
  17. package/__tests__/Search/Search.test.jsx +72 -0
  18. package/__tests__/Skeleton/Skeleton.test.jsx +1 -1
  19. package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
  20. package/__tests__/Tabs/Tabs.test.jsx +200 -0
  21. package/__tests__/Tags/Tags.test.jsx +1 -1
  22. package/__tests__/utils/input.test.js +58 -0
  23. package/__tests__/utils/useCopy.test.js +14 -3
  24. package/babel.config.js +20 -0
  25. package/jest.config.js +1 -1
  26. package/lib/A11yInfoProvider/index.js +54 -26
  27. package/lib/A11yText/index.js +37 -14
  28. package/lib/ActivityIndicator/Spinner.js +78 -0
  29. package/lib/ActivityIndicator/Spinner.native.js +121 -87
  30. package/lib/ActivityIndicator/index.js +28 -12
  31. package/lib/ActivityIndicator/shared.js +27 -12
  32. package/lib/BaseProvider/index.js +34 -11
  33. package/lib/Box/Box.js +54 -31
  34. package/lib/Box/index.js +13 -2
  35. package/lib/Button/Button.js +32 -11
  36. package/lib/Button/ButtonBase.js +85 -78
  37. package/lib/Button/ButtonGroup.js +94 -70
  38. package/lib/Button/ButtonLink.js +38 -15
  39. package/lib/Button/index.js +31 -4
  40. package/lib/Button/propTypes.js +32 -9
  41. package/lib/Card/Card.js +36 -41
  42. package/lib/Card/CardBase.js +78 -0
  43. package/lib/Card/PressableCardBase.js +137 -0
  44. package/lib/Card/index.js +40 -2
  45. package/lib/Checkbox/Checkbox.js +139 -103
  46. package/lib/Checkbox/CheckboxGroup.js +231 -0
  47. package/lib/Checkbox/CheckboxInput.js +74 -0
  48. package/lib/Checkbox/CheckboxInput.native.js +9 -1
  49. package/lib/Checkbox/index.js +21 -2
  50. package/lib/Divider/Divider.js +50 -24
  51. package/lib/Divider/index.js +13 -2
  52. package/lib/ExpandCollapse/Accordion.js +20 -7
  53. package/lib/ExpandCollapse/Control.js +50 -27
  54. package/lib/ExpandCollapse/ExpandCollapse.js +41 -24
  55. package/lib/ExpandCollapse/Panel.js +75 -37
  56. package/lib/ExpandCollapse/index.js +25 -7
  57. package/lib/Feedback/Feedback.js +69 -40
  58. package/lib/Feedback/index.js +13 -2
  59. package/lib/Fieldset/Fieldset.js +160 -0
  60. package/lib/Fieldset/FieldsetContainer.js +41 -0
  61. package/lib/Fieldset/FieldsetContainer.native.js +33 -0
  62. package/lib/Fieldset/Legend.js +33 -0
  63. package/lib/Fieldset/Legend.native.js +43 -0
  64. package/lib/Fieldset/cssReset.js +21 -0
  65. package/lib/Fieldset/index.js +13 -0
  66. package/lib/FlexGrid/Col/Col.js +67 -38
  67. package/lib/FlexGrid/Col/index.js +13 -2
  68. package/lib/FlexGrid/FlexGrid.js +70 -45
  69. package/lib/FlexGrid/Row/Row.js +48 -27
  70. package/lib/FlexGrid/Row/index.js +13 -2
  71. package/lib/FlexGrid/helpers/index.js +9 -1
  72. package/lib/FlexGrid/index.js +13 -2
  73. package/lib/FlexGrid/providers/GutterContext.js +15 -3
  74. package/lib/Icon/Icon.js +46 -44
  75. package/lib/Icon/IconText.js +49 -21
  76. package/lib/Icon/index.js +31 -4
  77. package/lib/InputLabel/InputLabel.js +70 -36
  78. package/lib/InputLabel/LabelContent.js +31 -0
  79. package/lib/InputLabel/LabelContent.native.js +9 -1
  80. package/lib/InputLabel/index.js +13 -2
  81. package/lib/InputSupports/InputSupports.js +62 -48
  82. package/lib/InputSupports/index.js +13 -2
  83. package/lib/InputSupports/propTypes.js +19 -8
  84. package/lib/InputSupports/useInputSupports.js +41 -0
  85. package/lib/Link/ChevronLink.js +33 -16
  86. package/lib/Link/InlinePressable.js +50 -0
  87. package/lib/Link/InlinePressable.native.js +34 -11
  88. package/lib/Link/Link.js +25 -9
  89. package/lib/Link/LinkBase.js +87 -57
  90. package/lib/Link/TextButton.js +32 -13
  91. package/lib/Link/index.js +39 -5
  92. package/lib/List/List.js +51 -23
  93. package/lib/List/ListItem.js +70 -40
  94. package/lib/List/index.js +13 -2
  95. package/lib/Modal/Modal.js +226 -0
  96. package/lib/Modal/dictionary.js +16 -0
  97. package/lib/Modal/index.js +13 -0
  98. package/lib/Notification/Notification.js +200 -0
  99. package/lib/Notification/dictionary.js +15 -0
  100. package/lib/Notification/index.js +13 -0
  101. package/lib/Pagination/PageButton.js +47 -25
  102. package/lib/Pagination/Pagination.js +70 -40
  103. package/lib/Pagination/SideButton.js +63 -37
  104. package/lib/Pagination/dictionary.js +9 -2
  105. package/lib/Pagination/index.js +13 -2
  106. package/lib/Pagination/usePagination.js +12 -2
  107. package/lib/Progress/Progress.js +99 -0
  108. package/lib/Progress/ProgressBar.js +146 -0
  109. package/lib/Progress/ProgressBarBackground.js +57 -0
  110. package/lib/Progress/index.js +16 -0
  111. package/lib/Radio/Radio.js +110 -109
  112. package/lib/Radio/RadioButton.js +141 -0
  113. package/lib/Radio/RadioGroup.js +233 -0
  114. package/lib/Radio/RadioInput.js +76 -0
  115. package/lib/Radio/RadioInput.native.js +9 -1
  116. package/lib/Radio/index.js +21 -2
  117. package/lib/RadioCard/RadioCard.js +240 -0
  118. package/lib/RadioCard/RadioCardGroup.js +251 -0
  119. package/lib/RadioCard/index.js +21 -0
  120. package/lib/Search/Search.js +243 -0
  121. package/lib/Search/dictionary.js +19 -0
  122. package/lib/Search/index.js +13 -0
  123. package/lib/Select/Group.js +33 -0
  124. package/lib/Select/Group.native.js +16 -5
  125. package/lib/Select/Item.js +29 -0
  126. package/lib/Select/Item.native.js +14 -4
  127. package/lib/Select/Picker.js +79 -0
  128. package/lib/Select/Picker.native.js +52 -24
  129. package/lib/Select/Select.js +110 -82
  130. package/lib/Select/index.js +19 -6
  131. package/lib/SideNav/Item.js +54 -33
  132. package/lib/SideNav/ItemContent.js +41 -15
  133. package/lib/SideNav/ItemsGroup.js +46 -27
  134. package/lib/SideNav/SideNav.js +92 -69
  135. package/lib/SideNav/index.js +15 -1
  136. package/lib/Skeleton/Skeleton.js +55 -37
  137. package/lib/Skeleton/index.js +13 -2
  138. package/lib/Skeleton/skeleton.constant.js +12 -0
  139. package/lib/Skeleton/skeletonWebAnimation.js +27 -0
  140. package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
  141. package/lib/Spacer/Spacer.js +31 -12
  142. package/lib/Spacer/index.js +13 -2
  143. package/lib/StackView/StackView.js +49 -27
  144. package/lib/StackView/StackWrap.js +33 -10
  145. package/lib/StackView/StackWrap.native.js +13 -2
  146. package/lib/StackView/StackWrapBox.js +46 -24
  147. package/lib/StackView/StackWrapGap.js +43 -22
  148. package/lib/StackView/common.js +19 -4
  149. package/lib/StackView/getStackedContent.js +49 -19
  150. package/lib/StackView/index.js +29 -5
  151. package/lib/StepTracker/Step.js +245 -0
  152. package/lib/StepTracker/StepTracker.js +197 -0
  153. package/lib/StepTracker/dictionary.js +17 -0
  154. package/lib/StepTracker/index.js +13 -0
  155. package/lib/Tabs/HorizontalScroll.js +199 -0
  156. package/lib/Tabs/ScrollViewEnd.js +66 -0
  157. package/lib/Tabs/ScrollViewEnd.native.js +41 -0
  158. package/lib/Tabs/Tabs.js +117 -0
  159. package/lib/Tabs/TabsItem.js +234 -0
  160. package/lib/Tabs/TabsScrollButton.js +121 -0
  161. package/lib/Tabs/dictionary.js +18 -0
  162. package/lib/Tabs/index.js +13 -0
  163. package/lib/Tabs/itemPositions.js +128 -0
  164. package/lib/Tags/Tags.js +130 -97
  165. package/lib/Tags/index.js +13 -2
  166. package/lib/TextInput/TextArea.js +51 -24
  167. package/lib/TextInput/TextInput.js +40 -19
  168. package/lib/TextInput/TextInputBase.js +78 -55
  169. package/lib/TextInput/index.js +23 -3
  170. package/lib/TextInput/propTypes.js +18 -7
  171. package/lib/ThemeProvider/ThemeProvider.js +38 -14
  172. package/lib/ThemeProvider/index.js +61 -6
  173. package/lib/ThemeProvider/useSetTheme.js +14 -5
  174. package/lib/ThemeProvider/useTheme.js +13 -4
  175. package/lib/ThemeProvider/useThemeTokens.js +32 -16
  176. package/lib/ThemeProvider/utils/index.js +31 -2
  177. package/lib/ThemeProvider/utils/styles.js +52 -16
  178. package/lib/ThemeProvider/utils/theme-tokens.js +94 -16
  179. package/lib/ToggleSwitch/ToggleSwitch.js +75 -51
  180. package/lib/ToggleSwitch/index.js +13 -2
  181. package/lib/Tooltip/{Backdrop.web.js → Backdrop.js} +22 -18
  182. package/lib/Tooltip/Backdrop.native.js +39 -15
  183. package/lib/Tooltip/Tooltip.js +112 -70
  184. package/lib/Tooltip/dictionary.js +9 -2
  185. package/lib/Tooltip/getTooltipPosition.js +9 -1
  186. package/lib/Tooltip/index.js +13 -2
  187. package/lib/TooltipButton/TooltipButton.js +57 -38
  188. package/lib/TooltipButton/index.js +13 -2
  189. package/lib/Typography/Typography.js +57 -27
  190. package/lib/Typography/index.js +13 -2
  191. package/lib/ViewportProvider/ViewportProvider.js +34 -13
  192. package/lib/ViewportProvider/index.js +28 -3
  193. package/lib/ViewportProvider/useViewport.js +15 -3
  194. package/lib/ViewportProvider/useViewportListener.js +24 -10
  195. package/lib/index.js +509 -33
  196. package/lib/utils/a11y/index.js +18 -1
  197. package/lib/utils/a11y/textSize.js +23 -7
  198. package/lib/utils/animation/index.js +15 -2
  199. package/lib/utils/animation/useVerticalExpandAnimation.js +28 -11
  200. package/lib/utils/children.js +87 -0
  201. package/lib/utils/index.js +163 -10
  202. package/lib/utils/info/index.js +18 -6
  203. package/lib/utils/info/platform/index.js +19 -7
  204. package/lib/utils/info/platform/platform.android.js +8 -1
  205. package/lib/utils/info/platform/platform.ios.js +8 -1
  206. package/lib/utils/info/platform/platform.js +8 -0
  207. package/lib/utils/info/platform/platform.native.js +8 -1
  208. package/lib/utils/info/versions.js +15 -4
  209. package/lib/utils/input.js +51 -33
  210. package/lib/utils/pressability.js +38 -10
  211. package/lib/utils/propTypes.js +217 -125
  212. package/lib/utils/useCopy.js +40 -5
  213. package/lib/utils/useHash.js +48 -0
  214. package/lib/utils/useHash.native.js +15 -0
  215. package/lib/utils/useResponsiveProp.js +21 -9
  216. package/lib/utils/useSpacingScale.js +21 -9
  217. package/lib/utils/useUniqueId.js +13 -4
  218. package/package.json +7 -6
  219. package/release-context.json +4 -4
  220. package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +0 -0
  221. package/src/Box/Box.jsx +11 -4
  222. package/src/Button/Button.jsx +3 -2
  223. package/src/Button/ButtonBase.jsx +27 -36
  224. package/src/Button/ButtonGroup.jsx +2 -2
  225. package/src/Button/ButtonLink.jsx +3 -2
  226. package/src/Button/propTypes.js +12 -2
  227. package/src/Card/Card.jsx +4 -30
  228. package/src/Card/CardBase.jsx +57 -0
  229. package/src/Card/PressableCardBase.jsx +112 -0
  230. package/src/Card/index.js +3 -0
  231. package/src/Checkbox/Checkbox.jsx +10 -11
  232. package/src/Checkbox/CheckboxGroup.jsx +196 -0
  233. package/src/Checkbox/{CheckboxInput.web.jsx → CheckboxInput.jsx} +0 -0
  234. package/src/Checkbox/index.js +2 -0
  235. package/src/ExpandCollapse/Control.jsx +1 -1
  236. package/src/Feedback/Feedback.jsx +1 -1
  237. package/src/Fieldset/Fieldset.jsx +129 -0
  238. package/src/Fieldset/FieldsetContainer.jsx +22 -0
  239. package/src/Fieldset/FieldsetContainer.native.jsx +16 -0
  240. package/src/Fieldset/Legend.jsx +16 -0
  241. package/src/Fieldset/Legend.native.jsx +22 -0
  242. package/src/Fieldset/cssReset.js +14 -0
  243. package/src/Fieldset/index.js +3 -0
  244. package/src/Icon/Icon.jsx +14 -23
  245. package/src/Icon/IconText.jsx +2 -2
  246. package/src/Icon/index.js +2 -2
  247. package/src/InputLabel/InputLabel.jsx +9 -2
  248. package/src/InputLabel/{LabelContent.web.jsx → LabelContent.jsx} +0 -0
  249. package/src/InputSupports/InputSupports.jsx +7 -18
  250. package/src/InputSupports/useInputSupports.js +30 -0
  251. package/src/Link/{InlinePressable.web.jsx → InlinePressable.jsx} +0 -0
  252. package/src/Link/LinkBase.jsx +14 -12
  253. package/src/Modal/Modal.jsx +185 -0
  254. package/src/Modal/dictionary.js +9 -0
  255. package/src/Modal/index.js +3 -0
  256. package/src/Notification/Notification.jsx +149 -0
  257. package/src/Notification/dictionary.js +8 -0
  258. package/src/Notification/index.js +3 -0
  259. package/src/Progress/Progress.jsx +77 -0
  260. package/src/Progress/ProgressBar.jsx +110 -0
  261. package/src/Progress/ProgressBarBackground.jsx +34 -0
  262. package/src/Progress/index.js +6 -0
  263. package/src/Radio/Radio.jsx +19 -56
  264. package/src/Radio/RadioButton.jsx +131 -0
  265. package/src/Radio/RadioGroup.jsx +198 -0
  266. package/src/Radio/{RadioInput.web.jsx → RadioInput.jsx} +0 -0
  267. package/src/Radio/index.js +2 -0
  268. package/src/RadioCard/RadioCard.jsx +191 -0
  269. package/src/RadioCard/RadioCardGroup.jsx +211 -0
  270. package/src/RadioCard/index.js +5 -0
  271. package/src/Search/Search.jsx +204 -0
  272. package/src/Search/dictionary.js +12 -0
  273. package/src/Search/index.js +3 -0
  274. package/src/Select/{Group.web.jsx → Group.jsx} +0 -0
  275. package/src/Select/{Item.web.jsx → Item.jsx} +0 -0
  276. package/src/Select/{Picker.web.jsx → Picker.jsx} +0 -0
  277. package/src/Select/Select.jsx +12 -22
  278. package/src/SideNav/Item.jsx +2 -2
  279. package/src/Skeleton/Skeleton.jsx +17 -20
  280. package/src/Skeleton/skeleton.constant.js +3 -0
  281. package/src/Skeleton/skeletonWebAnimation.js +13 -0
  282. package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
  283. package/src/StackView/StackView.jsx +10 -3
  284. package/src/StackView/StackWrap.jsx +9 -1
  285. package/src/StackView/StackWrapBox.jsx +4 -3
  286. package/src/StackView/StackWrapGap.jsx +3 -3
  287. package/src/StackView/getStackedContent.jsx +8 -2
  288. package/src/StepTracker/Step.jsx +202 -0
  289. package/src/StepTracker/StepTracker.jsx +163 -0
  290. package/src/StepTracker/dictionary.js +10 -0
  291. package/src/StepTracker/index.js +3 -0
  292. package/src/Tabs/HorizontalScroll.jsx +165 -0
  293. package/src/Tabs/ScrollViewEnd.jsx +53 -0
  294. package/src/Tabs/ScrollViewEnd.native.jsx +24 -0
  295. package/src/Tabs/Tabs.jsx +89 -0
  296. package/src/Tabs/TabsItem.jsx +204 -0
  297. package/src/Tabs/TabsScrollButton.jsx +100 -0
  298. package/src/Tabs/dictionary.js +11 -0
  299. package/src/Tabs/index.js +3 -0
  300. package/src/Tabs/itemPositions.js +101 -0
  301. package/src/Tags/Tags.jsx +2 -1
  302. package/src/TextInput/TextInputBase.jsx +12 -22
  303. package/src/ThemeProvider/useThemeTokens.js +2 -2
  304. package/src/ThemeProvider/utils/styles.js +18 -5
  305. package/src/ThemeProvider/utils/theme-tokens.js +46 -5
  306. package/src/ToggleSwitch/ToggleSwitch.jsx +2 -3
  307. package/src/Tooltip/{Backdrop.web.jsx → Backdrop.jsx} +0 -0
  308. package/src/Tooltip/Tooltip.jsx +1 -1
  309. package/src/TooltipButton/TooltipButton.jsx +23 -27
  310. package/src/Typography/Typography.jsx +6 -5
  311. package/src/index.js +20 -2
  312. package/src/utils/children.jsx +66 -0
  313. package/src/utils/index.js +3 -0
  314. package/src/utils/info/platform/platform.js +1 -0
  315. package/src/utils/info/versions.js +2 -2
  316. package/src/utils/input.js +20 -12
  317. package/src/utils/pressability.js +4 -0
  318. package/src/utils/propTypes.js +98 -34
  319. package/src/utils/useCopy.js +30 -4
  320. package/src/utils/useHash.js +34 -0
  321. package/src/utils/useHash.native.js +6 -0
  322. package/stories/A11yText/A11yText.stories.jsx +4 -8
  323. package/stories/Checkbox/Checkbox.stories.jsx +24 -1
  324. package/stories/Icon/Icon.stories.jsx +6 -5
  325. package/stories/Modal/Modal.stories.jsx +29 -0
  326. package/stories/Notification/Notification.stories.jsx +82 -0
  327. package/stories/Progress/Progress.stories.jsx +93 -0
  328. package/stories/Radio/Radio.stories.jsx +23 -36
  329. package/stories/RadioCard/RadioCard.stories.jsx +98 -0
  330. package/stories/Search/Search.stories.jsx +16 -0
  331. package/stories/StepTracker/StepTracker.stories.jsx +71 -0
  332. package/stories/Tabs/Tabs.stories.jsx +97 -0
  333. package/stories/{platform-supports.web.jsx → platform-supports.jsx} +0 -0
  334. package/__fixtures__/accessible.icon.svg +0 -6
  335. package/babel.config.json +0 -8
  336. package/lib/ActivityIndicator/Spinner.web.js +0 -55
  337. package/lib/Checkbox/CheckboxInput.web.js +0 -57
  338. package/lib/InputLabel/LabelContent.web.js +0 -17
  339. package/lib/Link/InlinePressable.web.js +0 -32
  340. package/lib/Radio/RadioInput.web.js +0 -59
  341. package/lib/Select/Group.web.js +0 -18
  342. package/lib/Select/Item.web.js +0 -15
  343. package/lib/Select/Picker.web.js +0 -63
  344. package/lib/config/svgr-icons-web.js +0 -9
  345. package/lib/config/svgr-icons.js +0 -52
  346. package/lib/utils/info/platform/platform.web.js +0 -1
  347. package/src/config/svgr-icons-web.js +0 -11
  348. package/src/config/svgr-icons.js +0 -46
  349. package/src/utils/info/platform/platform.web.js +0 -1
@@ -0,0 +1,200 @@
1
+ import React, { useState } from 'react'
2
+ import { Pressable, View, Text } from 'react-native'
3
+ import { fireEvent, render } from '@testing-library/react-native'
4
+
5
+ import { Tabs } from '../../src'
6
+ import {
7
+ getItemPositionLayoutHandler,
8
+ useItemPositions,
9
+ getItemPositionScrollTarget
10
+ } from '../../src/Tabs/itemPositions'
11
+ import Theme from '../../__fixtures__/Theme'
12
+
13
+ // ScrollViewRef.scrollTo doesn't work in Jest - unit-test the utilities instead
14
+ describe('Tabs getItemPositionScrollTarget', () => {
15
+ const positionsWithoutSpacing = {
16
+ 0: { start: 0, end: 100 },
17
+ 1: { start: 100, end: 200 },
18
+ 2: { start: 200, end: 300 }
19
+ }
20
+ const positions = {
21
+ 0: { start: 0, end: 50 },
22
+ 1: { start: 100, end: 150 },
23
+ 2: { start: 200, end: 250 }
24
+ }
25
+ it('scrolls to the start of an item rather than chopping it', () => {
26
+ const x = getItemPositionScrollTarget(150, 300, positionsWithoutSpacing)
27
+ expect(x).toBe(100)
28
+ })
29
+ it('offsets the position by a button clearance', () => {
30
+ const x = getItemPositionScrollTarget(150, 300, positionsWithoutSpacing, 20)
31
+ expect(x).toBe(80)
32
+ })
33
+ it('scrolls exactly if landing on a gap', () => {
34
+ const x = getItemPositionScrollTarget(170, 300, positions)
35
+ expect(x).toBe(170)
36
+ })
37
+ it('applies button clearance if landing on a gap', () => {
38
+ const x = getItemPositionScrollTarget(170, 300, positions, 40)
39
+ expect(x).toBe(130)
40
+ })
41
+ it('does not apply button clearance on reaching the end', () => {
42
+ const x = getItemPositionScrollTarget(300, 300, positions, 40)
43
+ expect(x).toBe(300)
44
+ })
45
+ it('does not exceed the maximum', () => {
46
+ const x = getItemPositionScrollTarget(320, 300, positions, 40)
47
+ expect(x).toBe(300)
48
+ })
49
+ it('does not go below 0', () => {
50
+ const x = getItemPositionScrollTarget(-420, 300, positions, 40)
51
+ expect(x).toBe(0)
52
+ })
53
+ })
54
+
55
+ // onLayout also doesn't work naturally in jest
56
+ describe('Tabs getItemPositionLayoutHandler', () => {
57
+ // Test component using useItemPositions with getItemPositionLayoutHandler
58
+ // that can be rerendered manually and that outputs itemPositions value
59
+ const MockComponent = () => {
60
+ const [num, setNum] = useState()
61
+ const [{ positions }] = useItemPositions()
62
+ return (
63
+ <View>
64
+ <View testID="onlayout[0]" onLayout={getItemPositionLayoutHandler(positions, 0)} />
65
+ <View testID="onlayout[1]" onLayout={getItemPositionLayoutHandler(positions, 1)} />
66
+ <Text testID="output">{JSON.stringify(positions)}</Text>
67
+ <Pressable testID="rerender" onPress={() => setNum(num + 1)}>
68
+ <Text>{num}</Text>
69
+ </Pressable>
70
+ </View>
71
+ )
72
+ }
73
+ it('gets width and x positions from onLayout events', async () => {
74
+ const { getByTestId } = render(<MockComponent />)
75
+
76
+ // onLayout doesn't work in jest but can be called directly as an event, but we
77
+ // have to pass the event object. Can't test that it gets them correctly from style
78
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
79
+ nativeEvent: {
80
+ layout: {
81
+ width: 200,
82
+ x: 0
83
+ }
84
+ }
85
+ })
86
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
87
+ nativeEvent: {
88
+ layout: {
89
+ width: 100,
90
+ x: 250
91
+ }
92
+ }
93
+ })
94
+ await fireEvent.press(getByTestId('rerender'))
95
+ expect(getByTestId('output')).toHaveTextContent(
96
+ '{"0":{"start":0,"end":200},"1":{"start":250,"end":350}}'
97
+ )
98
+ })
99
+ it('does not cause a rerender from onLayout events alone', async () => {
100
+ const { getByTestId } = render(<MockComponent />)
101
+
102
+ expect(getByTestId('output')).toHaveTextContent('{}')
103
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
104
+ nativeEvent: {
105
+ layout: {
106
+ width: 200,
107
+ x: 0
108
+ }
109
+ }
110
+ })
111
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
112
+ nativeEvent: {
113
+ layout: {
114
+ width: 100,
115
+ x: 250
116
+ }
117
+ }
118
+ })
119
+ expect(getByTestId('output')).toHaveTextContent('{}')
120
+ })
121
+ })
122
+
123
+ describe('useItemPositions', () => {
124
+ // Again we're limited in what we can test; we can't test natural onLayout
125
+ // or page load timing, but we can affirm that calling `setIsReady` after layout
126
+ // events causes a re-render that can access positions data
127
+ const IsReadyMockComponent = () => {
128
+ const [{ positions, setIsReady }] = useItemPositions()
129
+ return (
130
+ <View testID="container" onLayout={setIsReady}>
131
+ <View testID="onlayout[0]" onLayout={getItemPositionLayoutHandler(positions, 0)} />
132
+ <View testID="onlayout[1]" onLayout={getItemPositionLayoutHandler(positions, 1)} />
133
+ <Text testID="output">{JSON.stringify(positions)}</Text>
134
+ </View>
135
+ )
136
+ }
137
+ it('causes a rerender when setIsReady is called', async () => {
138
+ const { getByTestId } = render(<IsReadyMockComponent />)
139
+
140
+ expect(getByTestId('output')).toHaveTextContent('{}')
141
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
142
+ nativeEvent: {
143
+ layout: {
144
+ width: 200,
145
+ x: 0
146
+ }
147
+ }
148
+ })
149
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
150
+ nativeEvent: {
151
+ layout: {
152
+ width: 100,
153
+ x: 250
154
+ }
155
+ }
156
+ })
157
+ await fireEvent(getByTestId('container'), 'layout', {
158
+ nativeEvent: { layout: {} }
159
+ })
160
+
161
+ expect(getByTestId('output')).toHaveTextContent(
162
+ '{"0":{"start":0,"end":200},"1":{"start":250,"end":350}}'
163
+ )
164
+ })
165
+ })
166
+
167
+ describe('Tabs', () => {
168
+ const items = [{ label: 'one' }, { label: 'two' }, { label: 'three' }, { label: 'four' }]
169
+ const linkItems = items.map((item) => ({ ...item, href: 'https://telus.com' }))
170
+
171
+ it('renders a menu', () => {
172
+ const { queryAllByA11yRole } = render(<Tabs items={items} />, { wrapper: Theme })
173
+ expect(queryAllByA11yRole('tablist')).toHaveLength(1)
174
+ })
175
+
176
+ it('renders menuitems by default', () => {
177
+ const { queryAllByA11yRole } = render(<Tabs items={items} />, { wrapper: Theme })
178
+ expect(queryAllByA11yRole('tab')).toHaveLength(4)
179
+ expect(queryAllByA11yRole('link')).toHaveLength(0)
180
+ })
181
+
182
+ it('renders links by if hrefs are passed', () => {
183
+ const { queryAllByA11yRole } = render(<Tabs items={linkItems} />, { wrapper: Theme })
184
+ expect(queryAllByA11yRole('tab')).toHaveLength(0)
185
+ expect(queryAllByA11yRole('link')).toHaveLength(4)
186
+ })
187
+
188
+ it('is selected when pressed', () => {
189
+ const { queryByA11yState, getByText } = render(<Tabs items={items} />, { wrapper: Theme })
190
+ let selected
191
+ selected = queryByA11yState({ selected: true })
192
+ expect(selected).toBeFalsy()
193
+
194
+ fireEvent.press(getByText('two'))
195
+
196
+ selected = queryByA11yState({ selected: true })
197
+ expect(selected).toBeTruthy()
198
+ expect(selected).toHaveTextContent('two')
199
+ })
200
+ })
@@ -143,7 +143,7 @@ describe('Tags (uncontrolled)', () => {
143
143
  </Theme>
144
144
  )
145
145
 
146
- expect(queryAllByA11yRole('radioGroup')).toHaveLength(0)
146
+ expect(queryAllByA11yRole('radiogroup')).toHaveLength(0)
147
147
  expect(queryAllByA11yRole('radio')).toHaveLength(0)
148
148
 
149
149
  const checks = queryAllByA11yRole('checkbox')
@@ -90,6 +90,17 @@ describe('useInputValue (uncontrolled)', () => {
90
90
  expect(result.current.currentValue).toBe('some value')
91
91
  })
92
92
 
93
+ it('Changes currentValue based on old value when `setValue` is passed a function', () => {
94
+ const { result } = renderHook(() => useInputValue({ initialValue: 1 }))
95
+ expect(result.current.currentValue).toBe(1)
96
+
97
+ act(() => result.current.setValue((oldValue) => oldValue + 1))
98
+ expect(result.current.currentValue).toBe(2)
99
+
100
+ act(() => result.current.setValue((oldValue) => oldValue + 2))
101
+ expect(result.current.currentValue).toBe(4)
102
+ })
103
+
93
104
  it('Sets currentValue to initialValue if provided, which may be changed', () => {
94
105
  const { result } = renderHook(() => useInputValue({ initialValue: 'first value' }))
95
106
  expect(result.current.currentValue).toBe('first value')
@@ -210,6 +221,29 @@ describe('useMultipleInputValues (uncontrolled)', () => {
210
221
  expect(result.current.currentValues).toEqual(['second value', 'third value'])
211
222
  })
212
223
 
224
+ it('Replaces values on calling setValues', () => {
225
+ const { result } = renderHook(() =>
226
+ useMultipleInputValues({
227
+ initialValues: ['first value', 'second value', 'third value']
228
+ })
229
+ )
230
+ act(() => result.current.setValues(['new value', 'another value']))
231
+ expect(result.current.currentValues).toEqual(['new value', 'another value'])
232
+ })
233
+
234
+ it('Replaces values based on old values on passing function to setValues', () => {
235
+ const { result } = renderHook(() =>
236
+ useMultipleInputValues({
237
+ initialValues: [1, 2, 3, 4]
238
+ })
239
+ )
240
+ act(() => result.current.setValues((oldValues) => oldValues.map((value) => value + 1)))
241
+ expect(result.current.currentValues).toEqual([2, 3, 4, 5])
242
+
243
+ act(() => result.current.setValues((oldValues) => oldValues.map((value) => value + 2)))
244
+ expect(result.current.currentValues).toEqual([4, 5, 6, 7])
245
+ })
246
+
213
247
  it('Empties values on calling unsetValues', () => {
214
248
  const { result } = renderHook(() =>
215
249
  useMultipleInputValues({
@@ -237,6 +271,18 @@ describe('useInputValue (controlled)', () => {
237
271
  expect(onChange.mock.calls[0][0]).toEqual('second value')
238
272
  })
239
273
 
274
+ it('Calls `onChange` with result from old value when `setValue` is passed a function', () => {
275
+ const onChange = jest.fn((arg) => arg)
276
+ const { result } = renderHook(() => useInputValue({ value: 1, onChange }))
277
+ expect(result.current.currentValue).toBe(1)
278
+ expect(onChange).toHaveBeenCalledTimes(0)
279
+
280
+ act(() => result.current.setValue((oldValue) => oldValue + 1))
281
+ expect(result.current.currentValue).toBe(1)
282
+ expect(onChange).toHaveBeenCalledTimes(1)
283
+ expect(onChange.mock.calls[0][0]).toEqual(2)
284
+ })
285
+
240
286
  it('Returns updated `currentValue` when non-undefined `value` prop changes', () => {
241
287
  const onChange = () => {}
242
288
  const { result, rerender } = renderHook(({ value }) => useInputValue({ value, onChange }), {
@@ -296,6 +342,18 @@ describe('useMultipleInputValues (controlled)', () => {
296
342
  expect(onChange.mock.calls[0][0]).toEqual(['second value', 'third value'])
297
343
  })
298
344
 
345
+ it('Calls `onChange` with results from old values when `setValues` is passed a function', () => {
346
+ const onChange = jest.fn((arg) => arg)
347
+ const { result } = renderHook(() => useMultipleInputValues({ values: [1, 2, 3, 4], onChange }))
348
+ expect(result.current.currentValues).toEqual([1, 2, 3, 4])
349
+ expect(onChange).toHaveBeenCalledTimes(0)
350
+
351
+ act(() => result.current.setValues((oldValues) => oldValues.map((value) => value + 1)))
352
+ expect(result.current.currentValues).toEqual([1, 2, 3, 4])
353
+ expect(onChange).toHaveBeenCalledTimes(1)
354
+ expect(onChange.mock.calls[0][0]).toEqual([2, 3, 4, 5])
355
+ })
356
+
299
357
  it('Calls onChange with an empty array on calling unsetValues', () => {
300
358
  const onChange = jest.fn((arg) => arg)
301
359
  const { result, rerender } = renderHook(
@@ -14,18 +14,29 @@ describe('useCopy hook', () => {
14
14
  it('returns a correct english translation', () => {
15
15
  const { result } = renderHook(() => useCopy({ dictionary, copy: 'en' }))
16
16
 
17
- expect(result.current('translation key')).toBe('english version')
17
+ const getCopy = result.current
18
+ expect(getCopy('translation key')).toBe('english version')
18
19
  })
19
20
 
20
21
  it('returns a correct french translation', () => {
21
22
  const { result } = renderHook(() => useCopy({ dictionary, copy: 'fr' }))
22
23
 
23
- expect(result.current('translation key')).toBe('french version')
24
+ const getCopy = result.current
25
+ expect(getCopy('translation key')).toBe('french version')
24
26
  })
25
27
 
26
28
  it('returns undefined when no translation is found', () => {
27
29
  const { result } = renderHook(() => useCopy({ dictionary, copy: 'en' }))
28
30
 
29
- expect(result.current('non-existing key')).toBe(undefined)
31
+ const getCopy = result.current
32
+ expect(getCopy('non-existing key')).toBe(undefined)
33
+ })
34
+
35
+ it('allows for overriding the entire dictionary with a copy object (ignoring the dictionary argument)', () => {
36
+ const { result } = renderHook(() => useCopy({ dictionary, copy: dictionary.en }))
37
+
38
+ const getCopy = result.current
39
+ expect(getCopy('non-existing key')).toBe(undefined)
40
+ expect(getCopy('translation key')).toBe('english version')
30
41
  })
31
42
  })
@@ -0,0 +1,20 @@
1
+ module.exports = {
2
+ env: {
3
+ /*
4
+ * we actually want this setup to be used whenever we're not in `test` but
5
+ * babel merges plugins array rather than replacing so we can't set it as a
6
+ * default. However the default BABEL_ENV value is development (jest sets it
7
+ * to test)
8
+ */
9
+ development: {
10
+ presets: ['@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }]],
11
+ plugins: [['react-native-web', { commonjs: true }]]
12
+ },
13
+ /*
14
+ * jest is testing for just ios at the moment, use a preset which best matches that env
15
+ */
16
+ test: {
17
+ presets: ['module:metro-react-native-babel-preset']
18
+ }
19
+ }
20
+ }
package/jest.config.js CHANGED
@@ -22,7 +22,7 @@ module.exports = {
22
22
  '.+\\.(otf|svg|png|jpg)$': 'identity-obj-proxy'
23
23
  },
24
24
  transformIgnorePatterns: [
25
- 'node_modules/(?!(jest-)?react-native|@react-native-community|@react-native-picker)'
25
+ 'node_modules/(?!(jest-)?react-native|@react-native|@react-native-community|@react-native-picker)'
26
26
  ],
27
27
  // Count everything in src when calculating coverage
28
28
  collectCoverageFrom: ['src/**/*.{js,jsx}']
@@ -1,58 +1,86 @@
1
- import React, { createContext, useContext, useEffect, useState } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { AccessibilityInfo, Platform } from 'react-native';
4
- const ScreenReaderContext = /*#__PURE__*/createContext(false);
5
- const ReducedMotionContext = /*#__PURE__*/createContext(false);
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useA11yInfo = exports.default = void 0;
7
+
8
+ var _react = _interopRequireWildcard(require("react"));
9
+
10
+ var _propTypes = _interopRequireDefault(require("prop-types"));
11
+
12
+ var _AccessibilityInfo = _interopRequireDefault(require("react-native-web/dist/cjs/exports/AccessibilityInfo"));
13
+
14
+ var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
15
+
16
+ var _jsxRuntime = require("react/jsx-runtime");
17
+
18
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
+
20
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
21
+
22
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
23
+
24
+ const ScreenReaderContext = /*#__PURE__*/(0, _react.createContext)(false);
25
+ const ReducedMotionContext = /*#__PURE__*/(0, _react.createContext)(false);
6
26
 
7
27
  const A11yInfoProvider = ({
8
28
  children
9
29
  }) => {
10
- const [reduceMotionEnabled, setReduceMotionEnabled] = useState(false);
11
- const [screenReaderEnabled, setScreenReaderEnabled] = useState(false);
12
- useEffect(() => {
30
+ const [reduceMotionEnabled, setReduceMotionEnabled] = (0, _react.useState)(false);
31
+ const [screenReaderEnabled, setScreenReaderEnabled] = (0, _react.useState)(false);
32
+ (0, _react.useEffect)(() => {
13
33
  if (process.env.NODE_ENV === 'test') {
14
34
  // On Jest these effects do nothing but can cause `act` state change warnings
15
35
  // and "...after the Jest environment has been torn down" errors, so skip them.
16
36
  return () => {};
17
37
  }
18
38
 
19
- AccessibilityInfo.addEventListener('reduceMotionChanged', setReduceMotionEnabled);
20
- AccessibilityInfo.addEventListener('screenReaderChanged', setScreenReaderEnabled);
39
+ _AccessibilityInfo.default.addEventListener('reduceMotionChanged', setReduceMotionEnabled);
40
+
41
+ _AccessibilityInfo.default.addEventListener('screenReaderChanged', setScreenReaderEnabled);
21
42
 
22
43
  const setInitialA11yInfo = async () => {
23
- const [initialReduceMotionEnabled, initialScreenReaderEnabled] = await Promise.all([AccessibilityInfo.isReduceMotionEnabled(), AccessibilityInfo.isScreenReaderEnabled()]); // Browsers can't detect screen readers; in RNW isScreenReaderEnabled() is always `true`
44
+ const [initialReduceMotionEnabled, initialScreenReaderEnabled] = await Promise.all([_AccessibilityInfo.default.isReduceMotionEnabled(), _AccessibilityInfo.default.isScreenReaderEnabled()]); // Browsers can't detect screen readers; in RNW isScreenReaderEnabled() is always `true`
24
45
  // https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/AccessibilityInfo/index.js#L14
25
46
 
26
- setScreenReaderEnabled(Platform.OS !== 'web' && !!initialScreenReaderEnabled); // RNW does support isReduceMotionEnabled looking for 'prefers-reduced-motion' state
47
+ setScreenReaderEnabled(_Platform.default.OS !== 'web' && !!initialScreenReaderEnabled); // RNW does support isReduceMotionEnabled looking for 'prefers-reduced-motion' state
27
48
 
28
49
  setReduceMotionEnabled(!!initialReduceMotionEnabled);
29
50
  };
30
51
 
31
- if (AccessibilityInfo.isReduceMotionEnabled && AccessibilityInfo.isScreenReaderEnabled) {
52
+ if (_AccessibilityInfo.default.isReduceMotionEnabled && _AccessibilityInfo.default.isScreenReaderEnabled) {
32
53
  setInitialA11yInfo();
33
54
  }
34
55
 
35
56
  return () => {
36
- AccessibilityInfo.removeEventListener('reduceMotionChanged', setReduceMotionEnabled);
37
- AccessibilityInfo.removeEventListener('screenReaderChanged', setScreenReaderEnabled);
57
+ _AccessibilityInfo.default.removeEventListener('reduceMotionChanged', setReduceMotionEnabled);
58
+
59
+ _AccessibilityInfo.default.removeEventListener('screenReaderChanged', setScreenReaderEnabled);
38
60
  };
39
61
  }, []);
40
- return /*#__PURE__*/React.createElement(ReducedMotionContext.Provider, {
41
- value: reduceMotionEnabled
42
- }, /*#__PURE__*/React.createElement(ScreenReaderContext.Provider, {
43
- value: screenReaderEnabled
44
- }, children));
62
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(ReducedMotionContext.Provider, {
63
+ value: reduceMotionEnabled,
64
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ScreenReaderContext.Provider, {
65
+ value: screenReaderEnabled,
66
+ children: children
67
+ })
68
+ });
45
69
  };
46
70
 
47
71
  A11yInfoProvider.propTypes = {
48
- children: PropTypes.node.isRequired
72
+ children: _propTypes.default.node.isRequired
49
73
  };
50
- export default A11yInfoProvider;
51
- export const useA11yInfo = () => {
52
- const screenReaderEnabled = useContext(ScreenReaderContext);
53
- const reduceMotionEnabled = useContext(ReducedMotionContext);
74
+ var _default = A11yInfoProvider;
75
+ exports.default = _default;
76
+
77
+ const useA11yInfo = () => {
78
+ const screenReaderEnabled = (0, _react.useContext)(ScreenReaderContext);
79
+ const reduceMotionEnabled = (0, _react.useContext)(ReducedMotionContext);
54
80
  return {
55
81
  reduceMotionEnabled,
56
82
  screenReaderEnabled
57
83
  };
58
- };
84
+ };
85
+
86
+ exports.useA11yInfo = useA11yInfo;
@@ -1,39 +1,60 @@
1
- import React from 'react';
2
- import { Platform, StyleSheet, View } from 'react-native';
3
- import PropTypes from 'prop-types';
4
- import { a11yProps } from '../utils/propTypes';
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
11
+
12
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
13
+
14
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
15
+
16
+ var _propTypes = _interopRequireDefault(require("prop-types"));
17
+
18
+ var _propTypes2 = require("../utils/propTypes");
19
+
20
+ var _jsxRuntime = require("react/jsx-runtime");
21
+
22
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+
5
24
  /**
6
25
  * A11yText is a zero-size invisible element that adds text to be read by screen readers.
7
26
  *
8
27
  * It should be used to add selectable screen-reader-only text to the main document flow,
9
28
  * as a sibling to blocks of text like paragraphs and interactive elements like buttons.
10
29
  */
11
-
12
30
  const A11yText = ({
13
31
  text,
14
32
  heading,
15
33
  ...rest
16
34
  }) => {
17
- const a11y = a11yProps.select({
35
+ const a11y = _propTypes2.a11yProps.select({
18
36
  // On iOS, needs `accessible` to be true to be focusable without non-a11y content.
19
37
  // On Web, `accessible` causes RNW to set attributes that may make the element be treated as a group.
20
38
  // On Android, may cause this to be skipped when with `<Text>` siblings in an `accessible` View,
21
39
  // see https://github.com/facebook/react-native/issues/30851#issuecomment-790165489
22
- accessible: Platform.OS === 'ios',
40
+ accessible: _Platform.default.OS === 'ios',
23
41
  accessibilityLabel: text,
24
42
  accessibilityRole: heading ? 'header' : 'text',
25
43
  ...rest
26
44
  });
27
- return /*#__PURE__*/React.createElement(View, Object.assign({
28
- style: styles.invisible
29
- }, a11y));
45
+
46
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
47
+ style: styles.invisible,
48
+ ...a11y
49
+ });
30
50
  };
31
51
 
32
52
  A11yText.propTypes = {
33
- text: PropTypes.string.isRequired,
34
- heading: PropTypes.bool
53
+ text: _propTypes.default.string.isRequired,
54
+ heading: _propTypes.default.bool
35
55
  };
36
- const styles = StyleSheet.create({
56
+
57
+ const styles = _StyleSheet.default.create({
37
58
  invisible: {
38
59
  // Without width or height it is not shown
39
60
  minHeight: 1,
@@ -46,4 +67,6 @@ const styles = StyleSheet.create({
46
67
  top: -1
47
68
  }
48
69
  });
49
- export default A11yText;
70
+
71
+ var _default = A11yText;
72
+ exports.default = _default;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _shared = require("./shared");
11
+
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ const SVG_RADIUS = 20;
17
+ const SVG_CIRCUMFERENCE = SVG_RADIUS * 2 * Math.PI;
18
+ const MIN_SVG_LENGTH = _shared.MIN_STROKE_ANGLE / 360 * SVG_CIRCUMFERENCE;
19
+ const MAX_SVG_LENGTH = (1 - _shared.MIN_EMPTY_ANGLE / 360) * SVG_CIRCUMFERENCE;
20
+ const animationProps = {
21
+ begin: '0s',
22
+ dur: "".concat(_shared.DURATION, "ms"),
23
+ fill: 'freeze',
24
+ repeatCount: 'indefinite'
25
+ };
26
+ const bezierProps = {
27
+ calcMode: 'spline',
28
+ keyTimes: '0; 0.5; 1',
29
+ keySplines: "".concat(_shared.BEZIER.join(', '), " ; ").concat(_shared.BEZIER.join(', '))
30
+ }; // We're using svg rather than css here to define the animation to avoid needing to introduce css injection mechanism
31
+ // It's possible to replicate this functionality with RNW animations, but it snags on chrome at least, see https://github.com/telus/universal-design-system/pull/477 for details.
32
+
33
+ const Spinner = ({
34
+ size,
35
+ color,
36
+ thickness,
37
+ label
38
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
39
+ width: "".concat(size, "px"),
40
+ height: "".concat(size, "px"),
41
+ viewBox: "0 0 48 48",
42
+ "aria-valuetext": label,
43
+ role: "progressbar",
44
+ "aria-busy": true,
45
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("g", {
46
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("animateTransform", {
47
+ attributeName: "transform",
48
+ type: "rotate",
49
+ values: "-180 24 24;".concat(360 + _shared.MIN_STROKE_ANGLE - 180, " 24 24"),
50
+ ...animationProps
51
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("circle", {
52
+ fill: "none",
53
+ stroke: color,
54
+ strokeWidth: thickness * 48 / size,
55
+ strokeLinecap: "round",
56
+ cx: "24",
57
+ cy: "24",
58
+ r: "20",
59
+ strokeDasharray: [MIN_SVG_LENGTH, SVG_CIRCUMFERENCE],
60
+ strokeDashoffset: 0,
61
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("animate", {
62
+ attributeName: "stroke-dashoffset",
63
+ values: "0;-10;".concat(MIN_SVG_LENGTH - SVG_CIRCUMFERENCE),
64
+ ...animationProps,
65
+ ...bezierProps
66
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("animate", {
67
+ attributeName: "stroke-dasharray",
68
+ values: "".concat(MIN_SVG_LENGTH, ", 200;").concat(MAX_SVG_LENGTH, ", 200;").concat(MIN_SVG_LENGTH, ", 200"),
69
+ ...animationProps,
70
+ ...bezierProps
71
+ })]
72
+ })]
73
+ })
74
+ });
75
+
76
+ Spinner.propTypes = _shared.propTypes;
77
+ var _default = Spinner;
78
+ exports.default = _default;