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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (445) hide show
  1. package/.eslintrc.js +9 -0
  2. package/.ultra.cache.json +1 -1
  3. package/CHANGELOG.md +71 -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 +438 -31
  9. package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
  10. package/__tests__/Button/ButtonGroup.test.jsx +6 -7
  11. package/__tests__/Checkbox/Checkbox.test.jsx +2 -2
  12. package/__tests__/Checkbox/CheckboxGroup.test.jsx +246 -0
  13. package/__tests__/ExpandCollapse/ExpandCollapse.test.jsx +2 -2
  14. package/__tests__/HorizontalScroll/HorizontalScroll.test.jsx +164 -0
  15. package/__tests__/Icon/Icon.test.jsx +3 -3
  16. package/__tests__/IconButton/IconButton.test.jsx +52 -0
  17. package/__tests__/Link/LinkBase.test.jsx +0 -14
  18. package/__tests__/Modal/Modal.test.jsx +47 -0
  19. package/__tests__/Notification/Notification.test.jsx +20 -0
  20. package/__tests__/Pagination/Pagination.test.jsx +2 -2
  21. package/__tests__/Progress/Progress.test.jsx +79 -0
  22. package/__tests__/Radio/Radio.test.jsx +2 -2
  23. package/__tests__/Radio/RadioGroup.test.jsx +220 -0
  24. package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
  25. package/__tests__/RadioCard/RadioCardGroup.test.jsx +246 -0
  26. package/__tests__/Search/Search.test.jsx +73 -0
  27. package/__tests__/Select/Select.test.jsx +3 -2
  28. package/__tests__/Skeleton/Skeleton.test.jsx +1 -1
  29. package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
  30. package/__tests__/Tabs/Tabs.test.jsx +40 -0
  31. package/__tests__/Tags/Tags.test.jsx +5 -6
  32. package/__tests__/TextInput/TextArea.test.jsx +3 -2
  33. package/__tests__/TextInput/TextInputBase.test.jsx +10 -5
  34. package/__tests__/ThemeProvider/ThemeProvider.test.jsx +77 -0
  35. package/__tests__/ThemeProvider/useThemeTokens.test.jsx +9 -5
  36. package/__tests__/ThemeProvider/utils/theme-tokens.test.js +41 -0
  37. package/__tests__/ToggleSwitch/ToggleSwitch.test.jsx +3 -2
  38. package/__tests__/utils/children.test.jsx +128 -0
  39. package/__tests__/utils/input.test.js +59 -1
  40. package/__tests__/utils/semantics.test.jsx +43 -0
  41. package/__tests__/utils/useCopy.test.js +14 -3
  42. package/babel.config.js +20 -0
  43. package/jest.config.js +6 -3
  44. package/lib/A11yInfoProvider/index.js +54 -26
  45. package/lib/A11yText/index.js +45 -17
  46. package/lib/ActivityIndicator/Spinner.js +81 -0
  47. package/lib/ActivityIndicator/Spinner.native.js +129 -91
  48. package/lib/ActivityIndicator/index.js +28 -12
  49. package/lib/ActivityIndicator/shared.js +27 -12
  50. package/lib/BaseProvider/index.js +34 -11
  51. package/lib/Box/Box.js +153 -35
  52. package/lib/Box/index.js +13 -2
  53. package/lib/Button/Button.js +38 -16
  54. package/lib/Button/ButtonBase.js +93 -79
  55. package/lib/Button/ButtonGroup.js +112 -73
  56. package/lib/Button/ButtonLink.js +45 -19
  57. package/lib/Button/index.js +31 -4
  58. package/lib/Button/propTypes.js +32 -9
  59. package/lib/Card/Card.js +38 -41
  60. package/lib/Card/CardBase.js +86 -0
  61. package/lib/Card/PressableCardBase.js +141 -0
  62. package/lib/Card/index.js +40 -2
  63. package/lib/Checkbox/Checkbox.js +158 -111
  64. package/lib/Checkbox/CheckboxGroup.js +241 -0
  65. package/lib/Checkbox/CheckboxInput.js +74 -0
  66. package/lib/Checkbox/CheckboxInput.native.js +9 -1
  67. package/lib/Checkbox/index.js +21 -2
  68. package/lib/Divider/Divider.js +59 -28
  69. package/lib/Divider/index.js +13 -2
  70. package/lib/ExpandCollapse/Accordion.js +26 -7
  71. package/lib/ExpandCollapse/Control.js +60 -31
  72. package/lib/ExpandCollapse/ExpandCollapse.js +50 -28
  73. package/lib/ExpandCollapse/Panel.js +83 -44
  74. package/lib/ExpandCollapse/index.js +25 -7
  75. package/lib/Feedback/Feedback.js +77 -43
  76. package/lib/Feedback/index.js +13 -2
  77. package/lib/Fieldset/Fieldset.js +165 -0
  78. package/lib/Fieldset/FieldsetContainer.js +46 -0
  79. package/lib/Fieldset/FieldsetContainer.native.js +38 -0
  80. package/lib/Fieldset/Legend.js +38 -0
  81. package/lib/Fieldset/Legend.native.js +48 -0
  82. package/lib/Fieldset/cssReset.js +21 -0
  83. package/lib/Fieldset/index.js +13 -0
  84. package/lib/FlexGrid/Col/Col.js +73 -41
  85. package/lib/FlexGrid/Col/index.js +13 -2
  86. package/lib/FlexGrid/FlexGrid.js +99 -49
  87. package/lib/FlexGrid/Row/Row.js +58 -30
  88. package/lib/FlexGrid/Row/index.js +13 -2
  89. package/lib/FlexGrid/helpers/index.js +9 -1
  90. package/lib/FlexGrid/index.js +13 -2
  91. package/lib/FlexGrid/providers/GutterContext.js +15 -3
  92. package/lib/HorizontalScroll/HorizontalScroll.js +200 -0
  93. package/lib/HorizontalScroll/HorizontalScrollButton.js +127 -0
  94. package/lib/HorizontalScroll/ScrollViewEnd.js +66 -0
  95. package/lib/HorizontalScroll/ScrollViewEnd.native.js +41 -0
  96. package/lib/HorizontalScroll/dictionary.js +18 -0
  97. package/lib/HorizontalScroll/index.js +35 -0
  98. package/lib/HorizontalScroll/itemPositions.js +128 -0
  99. package/lib/Icon/Icon.js +57 -48
  100. package/lib/Icon/IconText.js +54 -25
  101. package/lib/Icon/index.js +31 -4
  102. package/lib/IconButton/IconButton.js +140 -0
  103. package/lib/IconButton/index.js +13 -0
  104. package/lib/InputLabel/InputLabel.js +102 -40
  105. package/lib/InputLabel/LabelContent.js +41 -0
  106. package/lib/InputLabel/LabelContent.native.js +32 -6
  107. package/lib/InputLabel/index.js +13 -2
  108. package/lib/InputSupports/InputSupports.js +71 -52
  109. package/lib/InputSupports/index.js +13 -2
  110. package/lib/InputSupports/propTypes.js +19 -8
  111. package/lib/InputSupports/useInputSupports.js +41 -0
  112. package/lib/Link/ChevronLink.js +44 -20
  113. package/lib/Link/InlinePressable.js +56 -0
  114. package/lib/Link/InlinePressable.native.js +39 -15
  115. package/lib/Link/Link.js +36 -13
  116. package/lib/Link/LinkBase.js +98 -61
  117. package/lib/Link/TextButton.js +41 -17
  118. package/lib/Link/index.js +39 -5
  119. package/lib/List/List.js +55 -26
  120. package/lib/List/ListItem.js +79 -41
  121. package/lib/List/index.js +13 -2
  122. package/lib/Modal/Modal.js +231 -0
  123. package/lib/Modal/dictionary.js +16 -0
  124. package/lib/Modal/index.js +13 -0
  125. package/lib/Notification/Notification.js +216 -0
  126. package/lib/Notification/dictionary.js +15 -0
  127. package/lib/Notification/index.js +13 -0
  128. package/lib/Pagination/PageButton.js +61 -28
  129. package/lib/Pagination/Pagination.js +78 -43
  130. package/lib/Pagination/SideButton.js +73 -42
  131. package/lib/Pagination/dictionary.js +9 -2
  132. package/lib/Pagination/index.js +13 -2
  133. package/lib/Pagination/usePagination.js +12 -2
  134. package/lib/Progress/Progress.js +104 -0
  135. package/lib/Progress/ProgressBar.js +157 -0
  136. package/lib/Progress/ProgressBarBackground.js +61 -0
  137. package/lib/Progress/index.js +16 -0
  138. package/lib/Radio/Radio.js +116 -114
  139. package/lib/Radio/RadioButton.js +152 -0
  140. package/lib/Radio/RadioGroup.js +244 -0
  141. package/lib/Radio/RadioInput.js +76 -0
  142. package/lib/Radio/RadioInput.native.js +9 -1
  143. package/lib/Radio/index.js +21 -2
  144. package/lib/RadioCard/RadioCard.js +244 -0
  145. package/lib/RadioCard/RadioCardGroup.js +252 -0
  146. package/lib/RadioCard/index.js +21 -0
  147. package/lib/Search/Search.js +254 -0
  148. package/lib/Search/dictionary.js +19 -0
  149. package/lib/Search/index.js +13 -0
  150. package/lib/Select/Group.js +33 -0
  151. package/lib/Select/Group.native.js +16 -5
  152. package/lib/Select/Item.js +29 -0
  153. package/lib/Select/Item.native.js +14 -4
  154. package/lib/Select/Picker.js +84 -0
  155. package/lib/Select/Picker.native.js +73 -30
  156. package/lib/Select/Select.js +155 -85
  157. package/lib/Select/index.js +19 -6
  158. package/lib/SideNav/Item.js +63 -37
  159. package/lib/SideNav/ItemContent.js +41 -15
  160. package/lib/SideNav/ItemsGroup.js +55 -31
  161. package/lib/SideNav/SideNav.js +100 -73
  162. package/lib/SideNav/index.js +15 -1
  163. package/lib/Skeleton/Skeleton.js +64 -46
  164. package/lib/Skeleton/index.js +13 -2
  165. package/lib/Skeleton/skeleton.constant.js +12 -0
  166. package/lib/Skeleton/skeletonWebAnimation.js +27 -0
  167. package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
  168. package/lib/Spacer/Spacer.js +49 -18
  169. package/lib/Spacer/index.js +13 -2
  170. package/lib/StackView/StackView.js +72 -31
  171. package/lib/StackView/StackWrap.js +43 -13
  172. package/lib/StackView/StackWrap.native.js +13 -2
  173. package/lib/StackView/StackWrapBox.js +77 -29
  174. package/lib/StackView/StackWrapGap.js +56 -26
  175. package/lib/StackView/common.js +23 -6
  176. package/lib/StackView/getStackedContent.js +47 -17
  177. package/lib/StackView/index.js +29 -5
  178. package/lib/StepTracker/Step.js +245 -0
  179. package/lib/StepTracker/StepTracker.js +202 -0
  180. package/lib/StepTracker/dictionary.js +17 -0
  181. package/lib/StepTracker/index.js +13 -0
  182. package/lib/Tabs/Tabs.js +124 -0
  183. package/lib/Tabs/TabsItem.js +238 -0
  184. package/lib/Tabs/index.js +13 -0
  185. package/lib/Tags/Tags.js +148 -99
  186. package/lib/Tags/index.js +13 -2
  187. package/lib/TextInput/TextArea.js +57 -28
  188. package/lib/TextInput/TextInput.js +50 -23
  189. package/lib/TextInput/TextInputBase.js +90 -63
  190. package/lib/TextInput/index.js +23 -3
  191. package/lib/TextInput/propTypes.js +18 -7
  192. package/lib/ThemeProvider/ThemeProvider.js +46 -18
  193. package/lib/ThemeProvider/index.js +61 -6
  194. package/lib/ThemeProvider/useSetTheme.js +19 -5
  195. package/lib/ThemeProvider/useTheme.js +13 -4
  196. package/lib/ThemeProvider/useThemeTokens.js +32 -16
  197. package/lib/ThemeProvider/utils/index.js +31 -2
  198. package/lib/ThemeProvider/utils/styles.js +50 -14
  199. package/lib/ThemeProvider/utils/theme-tokens.js +121 -12
  200. package/lib/ToggleSwitch/ToggleSwitch.js +85 -56
  201. package/lib/ToggleSwitch/index.js +13 -2
  202. package/lib/Tooltip/{Backdrop.web.js → Backdrop.js} +20 -8
  203. package/lib/Tooltip/Backdrop.native.js +39 -15
  204. package/lib/Tooltip/Tooltip.js +117 -74
  205. package/lib/Tooltip/dictionary.js +9 -2
  206. package/lib/Tooltip/getTooltipPosition.js +9 -1
  207. package/lib/Tooltip/index.js +13 -2
  208. package/lib/TooltipButton/TooltipButton.js +57 -38
  209. package/lib/TooltipButton/index.js +13 -2
  210. package/lib/Typography/Typography.js +87 -41
  211. package/lib/Typography/index.js +13 -2
  212. package/lib/ViewportProvider/ViewportProvider.js +34 -13
  213. package/lib/ViewportProvider/index.js +28 -3
  214. package/lib/ViewportProvider/useViewport.js +15 -3
  215. package/lib/ViewportProvider/useViewportListener.js +24 -10
  216. package/lib/index.js +539 -33
  217. package/lib/utils/a11y/index.js +31 -1
  218. package/lib/utils/a11y/semantics.js +173 -0
  219. package/lib/utils/a11y/textSize.js +23 -7
  220. package/lib/utils/animation/index.js +15 -2
  221. package/lib/utils/animation/useVerticalExpandAnimation.js +27 -10
  222. package/lib/utils/children.js +134 -0
  223. package/lib/utils/index.js +163 -10
  224. package/lib/utils/info/index.js +18 -6
  225. package/lib/utils/info/platform/index.js +19 -7
  226. package/lib/utils/info/platform/platform.android.js +8 -1
  227. package/lib/utils/info/platform/platform.ios.js +8 -1
  228. package/lib/utils/info/platform/platform.js +8 -0
  229. package/lib/utils/info/platform/platform.native.js +8 -1
  230. package/lib/utils/info/versions.js +15 -4
  231. package/lib/utils/input.js +53 -25
  232. package/lib/utils/pressability.js +38 -10
  233. package/lib/utils/propTypes.js +287 -141
  234. package/lib/utils/useCopy.js +40 -5
  235. package/lib/utils/useHash.js +52 -0
  236. package/lib/utils/useHash.native.js +15 -0
  237. package/lib/utils/useResponsiveProp.js +21 -9
  238. package/lib/utils/useSpacingScale.js +19 -9
  239. package/lib/utils/useUniqueId.js +12 -3
  240. package/package.json +14 -9
  241. package/release-context.json +4 -4
  242. package/src/A11yText/index.jsx +6 -4
  243. package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +5 -3
  244. package/src/ActivityIndicator/Spinner.native.jsx +5 -3
  245. package/src/Box/Box.jsx +132 -39
  246. package/src/Button/Button.jsx +10 -6
  247. package/src/Button/ButtonBase.jsx +99 -99
  248. package/src/Button/ButtonGroup.jsx +81 -69
  249. package/src/Button/ButtonLink.jsx +21 -15
  250. package/src/Button/propTypes.js +12 -2
  251. package/src/Card/Card.jsx +5 -31
  252. package/src/Card/CardBase.jsx +59 -0
  253. package/src/Card/PressableCardBase.jsx +119 -0
  254. package/src/Card/index.js +3 -0
  255. package/src/Checkbox/Checkbox.jsx +121 -112
  256. package/src/Checkbox/CheckboxGroup.jsx +206 -0
  257. package/src/Checkbox/{CheckboxInput.web.jsx → CheckboxInput.jsx} +0 -0
  258. package/src/Checkbox/index.js +2 -0
  259. package/src/Divider/Divider.jsx +7 -4
  260. package/src/ExpandCollapse/Accordion.jsx +3 -2
  261. package/src/ExpandCollapse/Control.jsx +40 -43
  262. package/src/ExpandCollapse/ExpandCollapse.jsx +26 -23
  263. package/src/ExpandCollapse/Panel.jsx +69 -63
  264. package/src/Feedback/Feedback.jsx +36 -33
  265. package/src/Fieldset/Fieldset.jsx +136 -0
  266. package/src/Fieldset/FieldsetContainer.jsx +31 -0
  267. package/src/Fieldset/FieldsetContainer.native.jsx +19 -0
  268. package/src/Fieldset/Legend.jsx +21 -0
  269. package/src/Fieldset/Legend.native.jsx +27 -0
  270. package/src/Fieldset/cssReset.js +14 -0
  271. package/src/Fieldset/index.js +3 -0
  272. package/src/FlexGrid/Col/Col.jsx +139 -132
  273. package/src/FlexGrid/FlexGrid.jsx +79 -51
  274. package/src/FlexGrid/Row/Row.jsx +55 -48
  275. package/src/HorizontalScroll/HorizontalScroll.jsx +168 -0
  276. package/src/HorizontalScroll/HorizontalScrollButton.jsx +105 -0
  277. package/src/HorizontalScroll/ScrollViewEnd.jsx +53 -0
  278. package/src/HorizontalScroll/ScrollViewEnd.native.jsx +24 -0
  279. package/src/HorizontalScroll/dictionary.js +11 -0
  280. package/src/HorizontalScroll/index.js +17 -0
  281. package/src/HorizontalScroll/itemPositions.js +101 -0
  282. package/src/Icon/Icon.jsx +43 -50
  283. package/src/Icon/IconText.jsx +23 -18
  284. package/src/Icon/index.js +2 -2
  285. package/src/IconButton/IconButton.jsx +114 -0
  286. package/src/IconButton/index.js +3 -0
  287. package/src/InputLabel/InputLabel.jsx +57 -35
  288. package/src/InputLabel/LabelContent.jsx +21 -0
  289. package/src/InputLabel/LabelContent.native.jsx +11 -2
  290. package/src/InputSupports/InputSupports.jsx +29 -45
  291. package/src/InputSupports/useInputSupports.js +30 -0
  292. package/src/Link/ChevronLink.jsx +26 -16
  293. package/src/Link/{InlinePressable.web.jsx → InlinePressable.jsx} +5 -3
  294. package/src/Link/InlinePressable.native.jsx +5 -3
  295. package/src/Link/Link.jsx +22 -16
  296. package/src/Link/LinkBase.jsx +76 -65
  297. package/src/Link/TextButton.jsx +30 -23
  298. package/src/List/List.jsx +5 -4
  299. package/src/List/ListItem.jsx +77 -82
  300. package/src/Modal/Modal.jsx +190 -0
  301. package/src/Modal/dictionary.js +9 -0
  302. package/src/Modal/index.js +3 -0
  303. package/src/Notification/Notification.jsx +164 -0
  304. package/src/Notification/dictionary.js +8 -0
  305. package/src/Notification/index.js +3 -0
  306. package/src/Pagination/PageButton.jsx +42 -35
  307. package/src/Pagination/Pagination.jsx +88 -92
  308. package/src/Pagination/SideButton.jsx +44 -41
  309. package/src/Progress/Progress.jsx +78 -0
  310. package/src/Progress/ProgressBar.jsx +123 -0
  311. package/src/Progress/ProgressBarBackground.jsx +36 -0
  312. package/src/Progress/index.js +6 -0
  313. package/src/Radio/Radio.jsx +82 -112
  314. package/src/Radio/RadioButton.jsx +142 -0
  315. package/src/Radio/RadioGroup.jsx +209 -0
  316. package/src/Radio/{RadioInput.web.jsx → RadioInput.jsx} +0 -0
  317. package/src/Radio/index.js +2 -0
  318. package/src/RadioCard/RadioCard.jsx +198 -0
  319. package/src/RadioCard/RadioCardGroup.jsx +218 -0
  320. package/src/RadioCard/index.js +5 -0
  321. package/src/Search/Search.jsx +225 -0
  322. package/src/Search/dictionary.js +12 -0
  323. package/src/Search/index.js +3 -0
  324. package/src/Select/{Group.web.jsx → Group.jsx} +0 -0
  325. package/src/Select/{Item.web.jsx → Item.jsx} +0 -0
  326. package/src/Select/Picker.jsx +74 -0
  327. package/src/Select/Picker.native.jsx +56 -49
  328. package/src/Select/Select.jsx +125 -92
  329. package/src/SideNav/Item.jsx +54 -47
  330. package/src/SideNav/ItemsGroup.jsx +50 -43
  331. package/src/SideNav/SideNav.jsx +68 -60
  332. package/src/Skeleton/Skeleton.jsx +25 -32
  333. package/src/Skeleton/skeleton.constant.js +3 -0
  334. package/src/Skeleton/skeletonWebAnimation.js +13 -0
  335. package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
  336. package/src/Spacer/Spacer.jsx +11 -4
  337. package/src/StackView/StackView.jsx +54 -23
  338. package/src/StackView/StackWrap.jsx +16 -7
  339. package/src/StackView/StackWrapBox.jsx +63 -28
  340. package/src/StackView/StackWrapGap.jsx +46 -24
  341. package/src/StackView/common.jsx +3 -2
  342. package/src/StackView/getStackedContent.jsx +8 -2
  343. package/src/StepTracker/Step.jsx +202 -0
  344. package/src/StepTracker/StepTracker.jsx +174 -0
  345. package/src/StepTracker/dictionary.js +10 -0
  346. package/src/StepTracker/index.js +3 -0
  347. package/src/Tabs/Tabs.jsx +97 -0
  348. package/src/Tabs/TabsItem.jsx +212 -0
  349. package/src/Tabs/index.js +3 -0
  350. package/src/Tags/Tags.jsx +115 -102
  351. package/src/TextInput/TextArea.jsx +5 -4
  352. package/src/TextInput/TextInput.jsx +5 -4
  353. package/src/TextInput/TextInputBase.jsx +95 -98
  354. package/src/ThemeProvider/ThemeProvider.jsx +11 -7
  355. package/src/ThemeProvider/useSetTheme.js +4 -0
  356. package/src/ThemeProvider/useThemeTokens.js +2 -2
  357. package/src/ThemeProvider/utils/styles.js +18 -5
  358. package/src/ThemeProvider/utils/theme-tokens.js +74 -5
  359. package/src/ToggleSwitch/ToggleSwitch.jsx +50 -52
  360. package/src/Tooltip/{Backdrop.web.jsx → Backdrop.jsx} +0 -0
  361. package/src/Tooltip/Tooltip.jsx +135 -131
  362. package/src/TooltipButton/TooltipButton.jsx +23 -27
  363. package/src/Typography/Typography.jsx +71 -47
  364. package/src/index.js +23 -2
  365. package/src/utils/a11y/index.js +1 -0
  366. package/src/utils/a11y/semantics.js +162 -0
  367. package/src/utils/children.jsx +119 -0
  368. package/src/utils/index.js +3 -0
  369. package/src/utils/info/platform/platform.js +1 -0
  370. package/src/utils/info/versions.js +2 -2
  371. package/src/utils/input.js +36 -25
  372. package/src/utils/pressability.js +4 -0
  373. package/src/utils/propTypes.js +199 -72
  374. package/src/utils/useCopy.js +30 -4
  375. package/src/utils/useHash.js +39 -0
  376. package/src/utils/useHash.native.js +6 -0
  377. package/stories/A11yText/A11yText.stories.jsx +6 -10
  378. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +1 -1
  379. package/stories/Box/Box.stories.jsx +1 -1
  380. package/stories/Button/Button.stories.jsx +2 -2
  381. package/stories/Button/ButtonGroup.stories.jsx +1 -1
  382. package/stories/Button/ButtonLink.stories.jsx +1 -1
  383. package/stories/Card/Card.stories.jsx +1 -1
  384. package/stories/Checkbox/Checkbox.stories.jsx +24 -1
  385. package/stories/Divider/Divider.stories.jsx +1 -1
  386. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +2 -2
  387. package/stories/Feedback/Feedback.stories.jsx +1 -1
  388. package/stories/FlexGrid/01 FlexGrid.stories.jsx +1 -1
  389. package/stories/FlexGrid/02 Row.stories.jsx +1 -1
  390. package/stories/FlexGrid/03 Col.stories.jsx +1 -1
  391. package/stories/Icon/Icon.stories.jsx +27 -7
  392. package/stories/IconButton/IconButton.stories.jsx +50 -0
  393. package/stories/InputLabel/InputLabel.stories.jsx +1 -1
  394. package/stories/Link/ChevronLink.stories.jsx +1 -1
  395. package/stories/Link/Link.stories.jsx +17 -21
  396. package/stories/Link/TextButton.stories.jsx +1 -1
  397. package/stories/List/List.stories.jsx +1 -1
  398. package/stories/Modal/Modal.stories.jsx +29 -0
  399. package/stories/Notification/Notification.stories.jsx +82 -0
  400. package/stories/Pagination/Pagination.stories.jsx +1 -1
  401. package/stories/Progress/Progress.stories.jsx +93 -0
  402. package/stories/Radio/Radio.stories.jsx +23 -36
  403. package/stories/RadioCard/RadioCard.stories.jsx +98 -0
  404. package/stories/Search/Search.stories.jsx +16 -0
  405. package/stories/Select/Select.stories.jsx +1 -1
  406. package/stories/SideNav/SideNav.stories.jsx +1 -1
  407. package/stories/SideNav/SideNavItem.stories.jsx +1 -1
  408. package/stories/SideNav/SideNavItemsGroup.stories.jsx +1 -1
  409. package/stories/Skeleton/Skeleton.stories.jsx +2 -2
  410. package/stories/Spacer/Spacer.stories.jsx +1 -1
  411. package/stories/StackView/StackView.stories.jsx +1 -1
  412. package/stories/StackView/StackWrap.stories.jsx +1 -1
  413. package/stories/StepTracker/StepTracker.stories.jsx +71 -0
  414. package/stories/Tabs/Tabs.stories.jsx +97 -0
  415. package/stories/Tags/Tags.stories.jsx +1 -1
  416. package/stories/TextInput/TextArea.stories.jsx +1 -1
  417. package/stories/TextInput/TextInput.stories.jsx +1 -1
  418. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +1 -1
  419. package/stories/Tooltip/Tooltip.stories.jsx +1 -1
  420. package/stories/TooltipButton/TooltipButton.stories.jsx +1 -1
  421. package/stories/Typography/Typography.stories.jsx +1 -1
  422. package/stories/{platform-supports.web.jsx → platform-supports.jsx} +1 -1
  423. package/stories/supports.jsx +37 -3
  424. package/__fixtures__/accessible.icon.svg +0 -6
  425. package/babel.config.json +0 -8
  426. package/docs/Contributing.stories.mdx +0 -9
  427. package/docs/Fonts.stories.mdx +0 -104
  428. package/docs/Icons.stories.mdx +0 -144
  429. package/docs/Introduction.stories.mdx +0 -9
  430. package/lib/ActivityIndicator/Spinner.web.js +0 -55
  431. package/lib/Checkbox/CheckboxInput.web.js +0 -57
  432. package/lib/InputLabel/LabelContent.web.js +0 -17
  433. package/lib/Link/InlinePressable.web.js +0 -32
  434. package/lib/Radio/RadioInput.web.js +0 -59
  435. package/lib/Select/Group.web.js +0 -18
  436. package/lib/Select/Item.web.js +0 -15
  437. package/lib/Select/Picker.web.js +0 -63
  438. package/lib/config/svgr-icons-web.js +0 -9
  439. package/lib/config/svgr-icons.js +0 -52
  440. package/lib/utils/info/platform/platform.web.js +0 -1
  441. package/src/InputLabel/LabelContent.web.jsx +0 -13
  442. package/src/Select/Picker.web.jsx +0 -67
  443. package/src/config/svgr-icons-web.js +0 -11
  444. package/src/config/svgr-icons.js +0 -46
  445. package/src/utils/info/platform/platform.web.js +0 -1
package/src/Tags/Tags.jsx CHANGED
@@ -1,8 +1,10 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
+ import ABBPropTypes from 'airbnb-prop-types'
3
4
  import { Platform, Text, View } from 'react-native'
4
5
 
5
6
  import ButtonBase from '../Button/ButtonBase'
7
+ import Icon from '../Icon'
6
8
  import { StackWrap, getStackedContent } from '../StackView'
7
9
  import { useViewport } from '../ViewportProvider'
8
10
  import { useThemeTokens, useThemeTokensCallback } from '../ThemeProvider'
@@ -50,106 +52,113 @@ const selectIconTextTokens = ({
50
52
  }
51
53
  })
52
54
 
53
- const Tags = ({
54
- variant,
55
- tokens,
56
- items = [],
57
- values,
58
- initialValues,
59
- maxValues,
60
- onChange,
61
- readOnly = false,
62
- inactive = false,
63
- accessibilityRole = Platform.select({ web: 'group', default: 'none' }),
64
- ...rest
65
- }) => {
66
- const viewport = useViewport()
67
- const themeTokens = useThemeTokens('Tags', tokens, variant, { viewport })
68
- const stackTokens = selectTokens('StackView', themeTokens)
69
- const { direction, space } = themeTokens
70
-
71
- const getItemTokens = useThemeTokensCallback('TagsItem', tokens, variant)
72
- const getButtonTokens = (buttonState) => selectTokens('Button', getItemTokens(buttonState))
73
-
74
- const { currentValues, toggleOneValue } = useMultipleInputValues({
75
- initialValues,
76
- values,
77
- maxValues,
78
- onChange,
79
- readOnly
80
- })
81
-
82
- const a11y = a11yProps.select({
83
- accessibilityRole,
84
- ...rest
85
- })
86
- const itemA11yRole = 'checkbox'
87
-
88
- return (
89
- <StackWrap {...a11y} space={space} direction={direction} tokens={stackTokens}>
90
- {items.map(({ label, id = label, accessibilityLabel }, index) => {
91
- const isSelected = currentValues.includes(id)
92
-
93
- // Pass an object of relevant component state as first argument for any passed-in press handlers
94
- const pressHandlers = getPressHandlersWithArgs(rest, [{ id, label, currentValues }])
95
-
96
- const handlePress = () => {
97
- if (pressHandlers.onPress) pressHandlers.onPress()
98
- toggleOneValue(id)
99
- }
100
-
101
- const itemA11y = {
102
- accessibilityState: { checked: isSelected },
103
- accessibilityRole: itemA11yRole,
104
- accessibilityLabel,
105
- ...a11yProps.getPositionInSet(items.length, index)
106
- }
107
-
108
- return (
109
- <ButtonBase
110
- key={id}
111
- {...pressHandlers}
112
- onPress={handlePress}
113
- tokens={getButtonTokens}
114
- selected={isSelected}
115
- inactive={inactive}
116
- {...itemA11y}
117
- >
118
- {({ textStyles, ...buttonState }) => {
119
- // TODO: once Icon/IconButton designs are stable, see if this sort of styling around
120
- // an icon should go in Icon itself, or possibly via an IconText token set. Related issues:
121
- // - Icon: https://github.com/telus/universal-design-system/issues/327
122
- // - IconButton: https://github.com/telus/universal-design-system/issues/281
123
- // - Token sets: https://github.com/telus/universal-design-system/issues/782
124
-
125
- const itemTokens = getItemTokens(buttonState)
126
-
127
- const {
128
- iconTokens,
129
- iconPosition,
130
- iconSpace,
131
- iconWrapperStyle,
132
- icon: IconComponent
133
- } = selectIconTextTokens(itemTokens)
134
-
135
- const iconContent = IconComponent ? (
136
- <View style={iconWrapperStyle}>
137
- <IconComponent tokens={iconTokens} />
138
- </View>
139
- ) : null
140
- const textContent = <Text style={textStyles}>{label}</Text>
141
-
142
- return getStackedContent(
143
- iconPosition === 'left' ? [iconContent, textContent] : [textContent, iconContent],
144
- { space: iconSpace, direction: 'row' }
145
- )
146
- }}
147
- </ButtonBase>
148
- )
149
- })}
150
- </StackWrap>
151
- )
152
- }
55
+ const Tags = forwardRef(
56
+ (
57
+ {
58
+ variant,
59
+ tokens,
60
+ items = [],
61
+ values,
62
+ initialValues,
63
+ maxValues,
64
+ onChange,
65
+ readOnly = false,
66
+ inactive = false,
67
+ accessibilityRole = Platform.select({ web: 'group', default: 'none' }),
68
+ ...rest
69
+ },
70
+ ref
71
+ ) => {
72
+ const viewport = useViewport()
73
+ const themeTokens = useThemeTokens('Tags', tokens, variant, { viewport })
74
+ const stackTokens = selectTokens('StackView', themeTokens)
75
+ const { direction, space } = themeTokens
76
+
77
+ const getItemTokens = useThemeTokensCallback('TagsItem', tokens, variant)
78
+ const getButtonTokens = (buttonState) => selectTokens('Button', getItemTokens(buttonState))
79
+
80
+ const { currentValues, toggleOneValue } = useMultipleInputValues({
81
+ initialValues,
82
+ values,
83
+ maxValues,
84
+ onChange,
85
+ readOnly
86
+ })
87
+
88
+ const a11y = a11yProps.select({
89
+ accessibilityRole,
90
+ ...rest
91
+ })
92
+ const itemA11yRole = 'checkbox'
93
+
94
+ return (
95
+ <StackWrap ref={ref} {...a11y} space={space} direction={direction} tokens={stackTokens}>
96
+ {items.map(({ label, id = label, accessibilityLabel, ref: itemRef }, index) => {
97
+ const isSelected = currentValues.includes(id)
98
+
99
+ // Pass an object of relevant component state as first argument for any passed-in press handlers
100
+ const pressHandlers = getPressHandlersWithArgs(rest, [{ id, label, currentValues }])
101
+
102
+ const handlePress = (event) => {
103
+ if (pressHandlers.onPress) pressHandlers.onPress()
104
+ toggleOneValue(id, event)
105
+ }
106
+
107
+ const itemA11y = {
108
+ accessibilityState: { checked: isSelected },
109
+ accessibilityRole: itemA11yRole,
110
+ accessibilityLabel,
111
+ ...a11yProps.getPositionInSet(items.length, index)
112
+ }
113
+
114
+ return (
115
+ <ButtonBase
116
+ ref={itemRef}
117
+ key={id}
118
+ {...pressHandlers}
119
+ onPress={handlePress}
120
+ tokens={getButtonTokens}
121
+ selected={isSelected}
122
+ inactive={inactive}
123
+ {...itemA11y}
124
+ >
125
+ {({ textStyles, ...buttonState }) => {
126
+ // TODO: once Icon/IconButton designs are stable, see if this sort of styling around
127
+ // an icon should go in Icon itself, or possibly via an IconText token set. Related issues:
128
+ // - Icon: https://github.com/telus/universal-design-system/issues/327
129
+ // - IconButton: https://github.com/telus/universal-design-system/issues/281
130
+ // - Token sets: https://github.com/telus/universal-design-system/issues/782
131
+
132
+ const itemTokens = getItemTokens(buttonState)
133
+
134
+ const {
135
+ iconTokens,
136
+ iconPosition,
137
+ iconSpace,
138
+ iconWrapperStyle,
139
+ icon: IconComponent
140
+ } = selectIconTextTokens(itemTokens)
141
+
142
+ const iconContent = IconComponent ? (
143
+ <View style={iconWrapperStyle}>
144
+ <Icon icon={IconComponent} tokens={iconTokens} />
145
+ </View>
146
+ ) : null
147
+ const textContent = <Text style={textStyles}>{label}</Text>
148
+
149
+ return getStackedContent(
150
+ iconPosition === 'left' ? [iconContent, textContent] : [textContent, iconContent],
151
+ { space: iconSpace, direction: 'row' }
152
+ )
153
+ }}
154
+ </ButtonBase>
155
+ )
156
+ })}
157
+ </StackWrap>
158
+ )
159
+ }
160
+ )
161
+ Tags.displayName = 'Tags'
153
162
 
154
163
  Tags.propTypes = {
155
164
  ...a11yProps.propTypes,
@@ -180,7 +189,11 @@ Tags.propTypes = {
180
189
  * which will be used in code and passed to any onChange function.
181
190
  * If not provided, the label is used.
182
191
  */
183
- id: PropTypes.string
192
+ id: PropTypes.string,
193
+ /**
194
+ * An optional ref for one individual Tag button in the tags
195
+ */
196
+ ref: ABBPropTypes.ref()
184
197
  })
185
198
  ),
186
199
  /**
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react'
1
+ import React, { forwardRef, useState } from 'react'
2
2
 
3
3
  import { Platform } from 'react-native'
4
4
  import { getTokensPropType, variantProp } from '../utils'
@@ -32,7 +32,7 @@ import textInputPropTypes from './propTypes'
32
32
  * or an indicator that the field is optional.
33
33
  * It is a more usable and accessible option than the HTML `placeholder` attribute.
34
34
  */
35
- function TextArea({ tokens, variant = {}, ...remainingProps }) {
35
+ const TextArea = forwardRef(({ tokens, variant = {}, ...remainingProps }, ref) => {
36
36
  const themeTokens = useThemeTokens('TextArea', tokens, variant)
37
37
  const [inputHeight, setInputHeight] = useState()
38
38
 
@@ -62,11 +62,12 @@ function TextArea({ tokens, variant = {}, ...remainingProps }) {
62
62
  return (
63
63
  <InputSupports {...supportsProps}>
64
64
  {({ a11yProps, inputId }) => (
65
- <TextInputBase {...inputProps} {...a11yProps} nativeID={inputId} />
65
+ <TextInputBase ref={ref} {...inputProps} {...a11yProps} nativeID={inputId} />
66
66
  )}
67
67
  </InputSupports>
68
68
  )
69
- }
69
+ })
70
+ TextArea.displayName = 'TextArea'
70
71
 
71
72
  TextArea.propTypes = {
72
73
  ...inputSupportProps.types,
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
 
3
3
  import { getTokensPropType, variantProp } from '../utils'
4
4
  import InputSupports from '../InputSupports'
@@ -24,7 +24,7 @@ import textInputPropTypes from './propTypes'
24
24
  * supported props and <a href="https://reactnative.dev/docs/textinput" target="_blank">React Native Web documentation</a> for
25
25
  * their implementation on the web.
26
26
  */
27
- function TextInput({ tokens, variant = {}, ...remainingProps }) {
27
+ const TextInput = forwardRef(({ tokens, variant = {}, ...remainingProps }, ref) => {
28
28
  const { props: supportsProps, rest } = inputSupportProps.select(remainingProps)
29
29
 
30
30
  const inputProps = {
@@ -36,11 +36,12 @@ function TextInput({ tokens, variant = {}, ...remainingProps }) {
36
36
  return (
37
37
  <InputSupports {...supportsProps}>
38
38
  {({ a11yProps, inputId }) => (
39
- <TextInputBase {...inputProps} {...a11yProps} nativeID={inputId} />
39
+ <TextInputBase ref={ref} {...inputProps} {...a11yProps} nativeID={inputId} />
40
40
  )}
41
41
  </InputSupports>
42
42
  )
43
- }
43
+ })
44
+ TextInput.displayName = 'TextInput'
44
45
 
45
46
  TextInput.propTypes = {
46
47
  ...inputSupportProps.types,
@@ -1,8 +1,8 @@
1
- import React, { useState } from 'react'
1
+ import React, { forwardRef, useState } from 'react'
2
2
  import { Platform, StyleSheet, TextInput as NativeTextInput, View } from 'react-native'
3
3
 
4
4
  import PropTypes from 'prop-types'
5
- import { applyTextStyles, useThemeTokens } from '../ThemeProvider'
5
+ import { applyTextStyles, useThemeTokens, applyOuterBorder } from '../ThemeProvider'
6
6
  import { getTokensPropType, useInputValue, variantProp } from '../utils'
7
7
 
8
8
  const selectInputStyles = (
@@ -76,27 +76,17 @@ const selectInputStyles = (
76
76
 
77
77
  const selectOuterBorderStyles = ({
78
78
  outerBackgroundColor,
79
- outerBorderWidth = 0,
79
+ outerBorderWidth,
80
80
  outerBorderColor,
81
- outerBorderRadius = 0
82
- }) => {
83
- // Use negative margins so that the outer border doesn't expand the input's bounding box
84
- const margin = -1 * outerBorderWidth
85
-
86
- // Account for the border width since we style it as an outline
87
- const borderRadius = outerBorderRadius + outerBorderWidth
88
-
89
- return {
90
- background: outerBackgroundColor,
91
- borderWidth: outerBorderWidth,
92
- borderColor: outerBorderColor,
93
- borderRadius,
94
- marginTop: margin,
95
- marginBottom: margin,
96
- marginLeft: margin,
97
- marginRight: margin
98
- }
99
- }
81
+ borderRadius
82
+ }) => ({
83
+ background: outerBackgroundColor,
84
+ ...applyOuterBorder({
85
+ outerBorderColor,
86
+ outerBorderWidth,
87
+ borderRadius
88
+ })
89
+ })
100
90
 
101
91
  const selectIconTokens = ({ iconSize, iconColor }) => ({
102
92
  size: iconSize,
@@ -108,90 +98,97 @@ const selectIconContainerStyles = ({ paddingRight, paddingBottom }) => ({
108
98
  paddingBottom
109
99
  })
110
100
 
111
- function TextInputBase({
112
- value,
113
- height,
114
- initialValue,
115
- inactive,
116
- readOnly,
117
- onChange,
118
- onChangeText,
119
- onFocus,
120
- onBlur,
121
- onMouseOver,
122
- onMouseOut,
123
- tokens,
124
- variant = {},
125
- ...remainingProps
126
- }) {
127
- const [isFocused, setIsFocused] = useState(false)
128
- const handleFocus = (event) => {
129
- setIsFocused(true)
130
- if (typeof onFocus === 'function') onFocus(event)
131
- }
132
- const handleBlur = (event) => {
133
- setIsFocused(false)
134
- if (typeof onBlur === 'function') onBlur(event)
135
- }
101
+ const TextInputBase = forwardRef(
102
+ (
103
+ {
104
+ value,
105
+ height,
106
+ initialValue,
107
+ inactive,
108
+ readOnly,
109
+ onChange,
110
+ onChangeText,
111
+ onFocus,
112
+ onBlur,
113
+ onMouseOver,
114
+ onMouseOut,
115
+ tokens,
116
+ variant = {},
117
+ ...remainingProps
118
+ },
119
+ ref
120
+ ) => {
121
+ const [isFocused, setIsFocused] = useState(false)
122
+ const handleFocus = (event) => {
123
+ setIsFocused(true)
124
+ if (typeof onFocus === 'function') onFocus(event)
125
+ }
126
+ const handleBlur = (event) => {
127
+ setIsFocused(false)
128
+ if (typeof onBlur === 'function') onBlur(event)
129
+ }
136
130
 
137
- const [isHovered, setIsHovered] = useState(false)
138
- const handleMouseOver = (event) => {
139
- setIsHovered(true)
140
- if (typeof onMouseOver === 'function') onMouseOver(event)
141
- }
142
- const handleMouseOut = (event) => {
143
- setIsHovered(false)
144
- if (typeof onMouseOut === 'function') onMouseOut(event)
145
- }
131
+ const [isHovered, setIsHovered] = useState(false)
132
+ const handleMouseOver = (event) => {
133
+ setIsHovered(true)
134
+ if (typeof onMouseOver === 'function') onMouseOver(event)
135
+ }
136
+ const handleMouseOut = (event) => {
137
+ setIsHovered(false)
138
+ if (typeof onMouseOut === 'function') onMouseOut(event)
139
+ }
146
140
 
147
- const { currentValue, setValue, isControlled } = useInputValue({
148
- value,
149
- initialValue,
150
- onChange,
151
- readOnly
152
- })
141
+ const { currentValue, setValue, isControlled } = useInputValue({
142
+ value,
143
+ initialValue,
144
+ onChange,
145
+ readOnly
146
+ })
147
+
148
+ const handleChangeText = (event) => {
149
+ const text = event.nativeEvent?.text || event.target?.value
150
+ setValue(text, event)
151
+ if (typeof onChangeText === 'function') onChangeText(text, event)
152
+ }
153
153
 
154
- const handleChangeText = (text) => {
155
- setValue(text)
156
- if (typeof onChangeText === 'function') onChangeText(text)
157
- }
154
+ const states = { focus: isFocused, hover: isHovered, inactive }
158
155
 
159
- const states = { focus: isFocused, hover: isHovered, inactive }
156
+ const themeTokens = useThemeTokens('TextInput', tokens, variant, states)
160
157
 
161
- const themeTokens = useThemeTokens('TextInput', tokens, variant, states)
158
+ const { icon: IconComponent } = themeTokens
162
159
 
163
- const { icon: IconComponent } = themeTokens
160
+ const inputProps = {
161
+ ...remainingProps,
162
+ editable: !inactive,
163
+ onFocus: handleFocus,
164
+ onBlur: handleBlur,
165
+ onMouseOver: handleMouseOver,
166
+ onMouseOut: handleMouseOut,
167
+ onChange: handleChangeText,
168
+ defaultValue: initialValue,
169
+ // currentValue is being updated even if the input is not controlled, passing it down to the
170
+ // Input could lead to changing its state from uncontrolled to controlled
171
+ value: isControlled ? currentValue : undefined
172
+ }
164
173
 
165
- const inputProps = {
166
- ...remainingProps,
167
- editable: !inactive,
168
- onFocus: handleFocus,
169
- onBlur: handleBlur,
170
- onMouseOver: handleMouseOver,
171
- onMouseOut: handleMouseOut,
172
- onChangeText: handleChangeText,
173
- defaultValue: initialValue,
174
- // currentValue is being updated even if the input is not controlled, passing it down to the
175
- // Input could lead to changing its state from uncontrolled to controlled
176
- value: isControlled ? currentValue : undefined
174
+ const nativeInputStyle = selectInputStyles({ ...themeTokens, height }, inactive)
175
+
176
+ return (
177
+ <View style={selectOuterBorderStyles(themeTokens)}>
178
+ <NativeTextInput ref={ref} style={nativeInputStyle} {...inputProps} />
179
+ {IconComponent && (
180
+ <View
181
+ pointerEvents="none" // avoid hijacking input press events
182
+ style={[staticStyles.iconContainer, selectIconContainerStyles(themeTokens)]}
183
+ >
184
+ <IconComponent {...selectIconTokens(themeTokens)} />
185
+ </View>
186
+ )}
187
+ </View>
188
+ )
177
189
  }
178
-
179
- const nativeInputStyle = selectInputStyles({ ...themeTokens, height }, inactive)
180
-
181
- return (
182
- <View style={selectOuterBorderStyles(themeTokens)}>
183
- <NativeTextInput style={nativeInputStyle} {...inputProps} />
184
- {IconComponent && (
185
- <View
186
- pointerEvents="none" // avoid hijacking input press events
187
- style={[staticStyles.iconContainer, selectIconContainerStyles(themeTokens)]}
188
- >
189
- <IconComponent tokens={selectIconTokens(themeTokens)} />
190
- </View>
191
- )}
192
- </View>
193
- )
194
- }
190
+ )
191
+ TextInputBase.displayName = 'TextInputBase'
195
192
 
196
193
  TextInputBase.propTypes = {
197
194
  value: PropTypes.string,
@@ -1,18 +1,20 @@
1
1
  import React, { createContext, useState } from 'react'
2
2
  import PropTypes from 'prop-types'
3
+ import { validateThemeTokensVersion } from './utils'
3
4
 
4
5
  export const uninitialisedError = new Error('Theme context used outside of ThemeProvider')
5
6
 
6
7
  export const ThemeContext = createContext(uninitialisedError)
7
8
  export const ThemeSetterContext = createContext(uninitialisedError)
8
9
 
9
- // TODO: develop this as theme metadata is added
10
- // https://github.com/telus/universal-design-system/issues/92
11
- export const themeType = PropTypes.object
12
-
13
10
  const ThemeProvider = ({ children, defaultTheme }) => {
14
11
  const [theme, setTheme] = useState(defaultTheme)
15
12
 
13
+ // Validate the theme tokens version on every render.
14
+ // This will intentionally break the application when attempting to use an invalid theme.
15
+ // This will surface an incompatibility quickly rather than allowing the potential for strange bugs due to missing or incompatible tokens.
16
+ validateThemeTokensVersion(theme)
17
+
16
18
  return (
17
19
  <ThemeSetterContext.Provider value={setTheme}>
18
20
  <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
@@ -21,10 +23,12 @@ const ThemeProvider = ({ children, defaultTheme }) => {
21
23
  }
22
24
 
23
25
  ThemeProvider.propTypes = {
24
- // TODO: implement a custom propType that validates schema version
25
- // https://github.com/telus/universal-design-system/issues/92
26
26
  children: PropTypes.node.isRequired,
27
- defaultTheme: themeType.isRequired
27
+ defaultTheme: PropTypes.shape({
28
+ metadata: PropTypes.shape({
29
+ themeTokensVersion: PropTypes.string.isRequired
30
+ }).isRequired
31
+ }).isRequired
28
32
  }
29
33
 
30
34
  export default ThemeProvider
@@ -4,6 +4,10 @@ import { ThemeSetterContext } from './ThemeProvider'
4
4
  const useSetTheme = () => {
5
5
  // Replace current theme with provided object
6
6
  const setTheme = useContext(ThemeSetterContext)
7
+ // Fail fast if dev uses useSetTheme outside of ThemeProvider
8
+ if (setTheme instanceof Error) {
9
+ throw setTheme
10
+ }
7
11
 
8
12
  // Merge provided object into current theme
9
13
  const editTheme = useCallback(
@@ -1,6 +1,6 @@
1
1
  import { useCallback } from 'react'
2
2
  import useTheme from './useTheme'
3
- import { getComponentTheme, getThemeTokens, resolveTokens, mergeAppearances } from './utils'
3
+ import { getComponentTheme, getThemeTokens, resolveThemeTokens, mergeAppearances } from './utils'
4
4
  /**
5
5
  * @typedef {import('../utils/propTypes.js').AppearanceSet} AppearanceSet
6
6
  * @typedef {import('../utils/propTypes.js').TokensProp} TokensProp
@@ -98,7 +98,7 @@ export const useThemeTokensCallback = (componentName, tokens = {}, variants = {}
98
98
  const getThemeTokensCallback = useCallback(
99
99
  (states, tokenOverrides) => {
100
100
  const appearances = mergeAppearances(variants, states)
101
- const resolvedTokens = resolveTokens(tokens, tokenOverrides, appearances)
101
+ const resolvedTokens = resolveThemeTokens(tokens, appearances, tokenOverrides)
102
102
  return getThemeTokens(componentTheme, resolvedTokens, appearances)
103
103
  },
104
104
  [componentTheme, tokens, variants]
@@ -9,6 +9,7 @@ import { fontBasePixels } from '@telus-uds/system-constants'
9
9
  // Make design tokens fit React Native's text styles' specific requirements and quirks
10
10
  export function applyTextStyles({
11
11
  fontSize,
12
+ fontScaleCap,
12
13
  lineHeight,
13
14
  letterSpacing,
14
15
  fontWeight = '400',
@@ -27,7 +28,7 @@ export function applyTextStyles({
27
28
  styles.lineHeight = lineHeight * (fontSize || fontBasePixels)
28
29
  }
29
30
 
30
- if (typeof letterSpacing === 'number') {
31
+ if (typeof letterSpacing === 'number' && letterSpacing) {
31
32
  // Same as for line heights - React Native expects absolute letter spacing value
32
33
  styles.letterSpacing = letterSpacing * (fontSize || fontBasePixels)
33
34
  }
@@ -133,7 +134,19 @@ export function verticalAlignRow(verticalAlign, reverse = false) {
133
134
  }
134
135
  }
135
136
 
136
- // React Native Views behave like flex blocks. There's no CSS 'display' and they can't inline themselves
137
- export function applyLayoutStyles() {
138
- // TODO: map design tokens to styles that implement inline, stretch, center, etc
139
- }
137
+ /**
138
+ * Use on an outer container to create an outer border with an optional gap around it
139
+ * that matches the border radius of any inner border.
140
+ */
141
+ export const applyOuterBorder = ({
142
+ outerBorderColor,
143
+ outerBorderWidth = 0,
144
+ outerBorderGap = 0,
145
+ borderRadius = 0
146
+ }) => ({
147
+ margin: 0 - outerBorderWidth - outerBorderGap,
148
+ padding: outerBorderGap,
149
+ borderRadius: borderRadius + outerBorderGap + outerBorderWidth,
150
+ borderWidth: outerBorderWidth,
151
+ borderColor: outerBorderColor
152
+ })