@telus-uds/components-base 0.0.2-prerelease.4 → 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 (447) hide show
  1. package/.ultra.cache.json +1 -0
  2. package/CHANGELOG.md +76 -0
  3. package/__fixtures__/Accessible.js +33 -0
  4. package/__fixtures__/Accessible.native.js +32 -0
  5. package/__fixtures__/testTheme.js +940 -54
  6. package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
  7. package/__tests__/Button/ButtonBase.test.jsx +3 -32
  8. package/__tests__/Button/ButtonGroup.test.jsx +2 -2
  9. package/__tests__/Checkbox/Checkbox.test.jsx +94 -0
  10. package/__tests__/Checkbox/CheckboxGroup.test.jsx +247 -0
  11. package/__tests__/Divider/Divider.test.jsx +26 -5
  12. package/__tests__/Feedback/Feedback.test.jsx +42 -0
  13. package/__tests__/Icon/Icon.test.jsx +3 -3
  14. package/__tests__/InputSupports/InputSupports.test.jsx +50 -0
  15. package/__tests__/List/List.test.jsx +60 -0
  16. package/__tests__/Modal/Modal.test.jsx +47 -0
  17. package/__tests__/Notification/Notification.test.jsx +20 -0
  18. package/__tests__/Pagination/Pagination.test.jsx +2 -2
  19. package/__tests__/Progress/Progress.test.jsx +79 -0
  20. package/__tests__/Radio/Radio.test.jsx +87 -0
  21. package/__tests__/Radio/RadioGroup.test.jsx +221 -0
  22. package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
  23. package/__tests__/RadioCard/RadioCardGroup.test.jsx +247 -0
  24. package/__tests__/Search/Search.test.jsx +72 -0
  25. package/__tests__/Select/Select.test.jsx +93 -0
  26. package/__tests__/Skeleton/Skeleton.test.jsx +61 -0
  27. package/__tests__/Spacer/Spacer.test.jsx +63 -0
  28. package/__tests__/StackView/StackView.test.jsx +216 -0
  29. package/__tests__/StackView/StackWrap.test.jsx +47 -0
  30. package/__tests__/StackView/getStackedContent.test.jsx +295 -0
  31. package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
  32. package/__tests__/Tabs/Tabs.test.jsx +200 -0
  33. package/__tests__/Tags/Tags.test.jsx +328 -0
  34. package/__tests__/TextInput/TextArea.test.jsx +34 -0
  35. package/__tests__/TextInput/TextInputBase.test.jsx +120 -0
  36. package/__tests__/Tooltip/Tooltip.test.jsx +65 -0
  37. package/__tests__/Tooltip/getTooltipPosition.test.js +79 -0
  38. package/__tests__/utils/input.test.js +58 -0
  39. package/__tests__/utils/useCopy.test.js +42 -0
  40. package/__tests__/utils/useResponsiveProp.test.jsx +202 -0
  41. package/__tests__/utils/{spacing.test.jsx → useSpacingScale.test.jsx} +1 -1
  42. package/__tests__/utils/useUniqueId.test.js +31 -0
  43. package/babel.config.js +20 -0
  44. package/jest.config.js +8 -2
  45. package/lib/A11yInfoProvider/index.js +54 -26
  46. package/lib/A11yText/index.js +37 -14
  47. package/lib/ActivityIndicator/Spinner.js +78 -0
  48. package/lib/ActivityIndicator/Spinner.native.js +121 -87
  49. package/lib/ActivityIndicator/index.js +28 -12
  50. package/lib/ActivityIndicator/shared.js +27 -12
  51. package/lib/BaseProvider/index.js +34 -11
  52. package/lib/Box/Box.js +56 -28
  53. package/lib/Box/index.js +13 -2
  54. package/lib/Button/Button.js +38 -10
  55. package/lib/Button/ButtonBase.js +120 -109
  56. package/lib/Button/ButtonGroup.js +98 -99
  57. package/lib/Button/ButtonLink.js +41 -13
  58. package/lib/Button/index.js +31 -4
  59. package/lib/Button/propTypes.js +32 -9
  60. package/lib/Card/Card.js +36 -41
  61. package/lib/Card/CardBase.js +78 -0
  62. package/lib/Card/PressableCardBase.js +137 -0
  63. package/lib/Card/index.js +40 -2
  64. package/lib/Checkbox/Checkbox.js +344 -0
  65. package/lib/Checkbox/CheckboxGroup.js +231 -0
  66. package/lib/Checkbox/CheckboxInput.js +74 -0
  67. package/lib/Checkbox/CheckboxInput.native.js +14 -0
  68. package/lib/Checkbox/index.js +21 -0
  69. package/lib/Divider/Divider.js +81 -17
  70. package/lib/Divider/index.js +13 -2
  71. package/lib/ExpandCollapse/Accordion.js +20 -7
  72. package/lib/ExpandCollapse/Control.js +50 -27
  73. package/lib/ExpandCollapse/ExpandCollapse.js +41 -24
  74. package/lib/ExpandCollapse/Panel.js +75 -37
  75. package/lib/ExpandCollapse/index.js +25 -7
  76. package/lib/Feedback/Feedback.js +161 -0
  77. package/lib/Feedback/index.js +13 -0
  78. package/lib/Fieldset/Fieldset.js +160 -0
  79. package/lib/Fieldset/FieldsetContainer.js +41 -0
  80. package/lib/Fieldset/FieldsetContainer.native.js +33 -0
  81. package/lib/Fieldset/Legend.js +33 -0
  82. package/lib/Fieldset/Legend.native.js +43 -0
  83. package/lib/Fieldset/cssReset.js +21 -0
  84. package/lib/Fieldset/index.js +13 -0
  85. package/lib/FlexGrid/Col/Col.js +67 -38
  86. package/lib/FlexGrid/Col/index.js +13 -2
  87. package/lib/FlexGrid/FlexGrid.js +70 -45
  88. package/lib/FlexGrid/Row/Row.js +48 -27
  89. package/lib/FlexGrid/Row/index.js +13 -2
  90. package/lib/FlexGrid/helpers/index.js +9 -1
  91. package/lib/FlexGrid/index.js +13 -2
  92. package/lib/FlexGrid/providers/GutterContext.js +15 -3
  93. package/lib/Icon/Icon.js +52 -47
  94. package/lib/Icon/IconText.js +100 -0
  95. package/lib/Icon/index.js +31 -3
  96. package/lib/InputLabel/InputLabel.js +122 -0
  97. package/lib/InputLabel/LabelContent.js +31 -0
  98. package/lib/InputLabel/LabelContent.native.js +16 -0
  99. package/lib/InputLabel/index.js +13 -0
  100. package/lib/InputSupports/InputSupports.js +104 -0
  101. package/lib/InputSupports/index.js +13 -0
  102. package/lib/InputSupports/propTypes.js +66 -0
  103. package/lib/InputSupports/useInputSupports.js +41 -0
  104. package/lib/Link/ChevronLink.js +57 -15
  105. package/lib/Link/InlinePressable.js +50 -0
  106. package/lib/Link/InlinePressable.native.js +101 -0
  107. package/lib/Link/Link.js +30 -13
  108. package/lib/Link/LinkBase.js +121 -146
  109. package/lib/Link/TextButton.js +47 -17
  110. package/lib/Link/index.js +39 -4
  111. package/lib/List/List.js +80 -0
  112. package/lib/List/ListItem.js +237 -0
  113. package/lib/List/index.js +13 -0
  114. package/lib/Modal/Modal.js +226 -0
  115. package/lib/Modal/dictionary.js +16 -0
  116. package/lib/Modal/index.js +13 -0
  117. package/lib/Notification/Notification.js +200 -0
  118. package/lib/Notification/dictionary.js +15 -0
  119. package/lib/Notification/index.js +13 -0
  120. package/lib/Pagination/PageButton.js +45 -46
  121. package/lib/Pagination/Pagination.js +70 -40
  122. package/lib/Pagination/SideButton.js +74 -58
  123. package/lib/Pagination/dictionary.js +9 -2
  124. package/lib/Pagination/index.js +13 -2
  125. package/lib/Pagination/usePagination.js +12 -2
  126. package/lib/Progress/Progress.js +99 -0
  127. package/lib/Progress/ProgressBar.js +146 -0
  128. package/lib/Progress/ProgressBarBackground.js +57 -0
  129. package/lib/Progress/index.js +16 -0
  130. package/lib/Radio/Radio.js +292 -0
  131. package/lib/Radio/RadioButton.js +141 -0
  132. package/lib/Radio/RadioGroup.js +233 -0
  133. package/lib/Radio/RadioInput.js +76 -0
  134. package/lib/Radio/RadioInput.native.js +14 -0
  135. package/lib/Radio/index.js +21 -0
  136. package/lib/RadioCard/RadioCard.js +240 -0
  137. package/lib/RadioCard/RadioCardGroup.js +251 -0
  138. package/lib/RadioCard/index.js +21 -0
  139. package/lib/Search/Search.js +243 -0
  140. package/lib/Search/dictionary.js +19 -0
  141. package/lib/Search/index.js +13 -0
  142. package/lib/Select/Group.js +33 -0
  143. package/lib/Select/Group.native.js +25 -0
  144. package/lib/Select/Item.js +29 -0
  145. package/lib/Select/Item.native.js +19 -0
  146. package/lib/Select/Picker.js +79 -0
  147. package/lib/Select/Picker.native.js +115 -0
  148. package/lib/Select/Select.js +300 -0
  149. package/lib/Select/index.js +19 -0
  150. package/lib/SideNav/Item.js +54 -33
  151. package/lib/SideNav/ItemContent.js +41 -15
  152. package/lib/SideNav/ItemsGroup.js +46 -27
  153. package/lib/SideNav/SideNav.js +92 -69
  154. package/lib/SideNav/index.js +15 -1
  155. package/lib/Skeleton/Skeleton.js +137 -0
  156. package/lib/Skeleton/index.js +13 -0
  157. package/lib/Skeleton/skeleton.constant.js +12 -0
  158. package/lib/Skeleton/skeletonWebAnimation.js +27 -0
  159. package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
  160. package/lib/Spacer/Spacer.js +117 -0
  161. package/lib/Spacer/index.js +13 -0
  162. package/lib/StackView/StackView.js +129 -0
  163. package/lib/StackView/StackWrap.js +55 -0
  164. package/lib/StackView/StackWrap.native.js +14 -0
  165. package/lib/StackView/StackWrapBox.js +112 -0
  166. package/lib/StackView/StackWrapGap.js +71 -0
  167. package/lib/StackView/common.js +45 -0
  168. package/lib/StackView/getStackedContent.js +141 -0
  169. package/lib/StackView/index.js +29 -0
  170. package/lib/StepTracker/Step.js +245 -0
  171. package/lib/StepTracker/StepTracker.js +197 -0
  172. package/lib/StepTracker/dictionary.js +17 -0
  173. package/lib/StepTracker/index.js +13 -0
  174. package/lib/Tabs/HorizontalScroll.js +199 -0
  175. package/lib/Tabs/ScrollViewEnd.js +66 -0
  176. package/lib/Tabs/ScrollViewEnd.native.js +41 -0
  177. package/lib/Tabs/Tabs.js +117 -0
  178. package/lib/Tabs/TabsItem.js +234 -0
  179. package/lib/Tabs/TabsScrollButton.js +121 -0
  180. package/lib/Tabs/dictionary.js +18 -0
  181. package/lib/Tabs/index.js +13 -0
  182. package/lib/Tabs/itemPositions.js +128 -0
  183. package/lib/Tags/Tags.js +250 -0
  184. package/lib/Tags/index.js +13 -0
  185. package/lib/TextInput/TextArea.js +109 -0
  186. package/lib/TextInput/TextInput.js +75 -0
  187. package/lib/TextInput/TextInputBase.js +252 -0
  188. package/lib/TextInput/index.js +23 -0
  189. package/lib/TextInput/propTypes.js +42 -0
  190. package/lib/ThemeProvider/ThemeProvider.js +38 -14
  191. package/lib/ThemeProvider/index.js +61 -6
  192. package/lib/ThemeProvider/useSetTheme.js +14 -5
  193. package/lib/ThemeProvider/useTheme.js +13 -4
  194. package/lib/ThemeProvider/useThemeTokens.js +86 -19
  195. package/lib/ThemeProvider/utils/index.js +31 -2
  196. package/lib/ThemeProvider/utils/styles.js +52 -16
  197. package/lib/ThemeProvider/utils/theme-tokens.js +94 -16
  198. package/lib/ToggleSwitch/ToggleSwitch.js +76 -52
  199. package/lib/ToggleSwitch/index.js +13 -2
  200. package/lib/Tooltip/Backdrop.js +56 -0
  201. package/lib/Tooltip/Backdrop.native.js +59 -0
  202. package/lib/Tooltip/Tooltip.js +357 -0
  203. package/lib/Tooltip/dictionary.js +15 -0
  204. package/lib/Tooltip/getTooltipPosition.js +172 -0
  205. package/lib/Tooltip/index.js +13 -0
  206. package/lib/TooltipButton/TooltipButton.js +83 -0
  207. package/lib/TooltipButton/index.js +13 -0
  208. package/lib/Typography/Typography.js +58 -47
  209. package/lib/Typography/index.js +13 -2
  210. package/lib/ViewportProvider/ViewportProvider.js +46 -0
  211. package/lib/ViewportProvider/index.js +22 -38
  212. package/lib/ViewportProvider/useViewport.js +15 -0
  213. package/lib/ViewportProvider/useViewportListener.js +57 -0
  214. package/lib/index.js +509 -19
  215. package/lib/utils/a11y/index.js +18 -0
  216. package/lib/utils/a11y/textSize.js +49 -0
  217. package/lib/utils/animation/index.js +15 -2
  218. package/lib/utils/animation/useVerticalExpandAnimation.js +28 -11
  219. package/lib/utils/children.js +87 -0
  220. package/lib/utils/index.js +163 -4
  221. package/lib/utils/info/index.js +19 -0
  222. package/lib/utils/info/platform/index.js +23 -0
  223. package/lib/utils/info/platform/platform.android.js +8 -0
  224. package/lib/utils/info/platform/platform.ios.js +8 -0
  225. package/lib/utils/info/platform/platform.js +8 -0
  226. package/lib/utils/info/platform/platform.native.js +11 -0
  227. package/lib/utils/info/versions.js +16 -0
  228. package/lib/utils/input.js +54 -34
  229. package/lib/utils/pressability.js +120 -0
  230. package/lib/utils/propTypes.js +269 -108
  231. package/lib/utils/useCopy.js +51 -0
  232. package/lib/utils/useHash.js +48 -0
  233. package/lib/utils/useHash.native.js +15 -0
  234. package/lib/utils/useResponsiveProp.js +59 -0
  235. package/lib/utils/{spacing/useSpacingScale.js → useSpacingScale.js} +45 -12
  236. package/lib/utils/useUniqueId.js +21 -0
  237. package/package.json +11 -8
  238. package/release-context.json +4 -4
  239. package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +0 -0
  240. package/src/Box/Box.jsx +13 -4
  241. package/src/Button/Button.jsx +9 -5
  242. package/src/Button/ButtonBase.jsx +74 -86
  243. package/src/Button/ButtonGroup.jsx +24 -41
  244. package/src/Button/ButtonLink.jsx +14 -4
  245. package/src/Button/propTypes.js +12 -2
  246. package/src/Card/Card.jsx +4 -30
  247. package/src/Card/CardBase.jsx +57 -0
  248. package/src/Card/PressableCardBase.jsx +112 -0
  249. package/src/Card/index.js +3 -0
  250. package/src/Checkbox/Checkbox.jsx +274 -0
  251. package/src/Checkbox/CheckboxGroup.jsx +196 -0
  252. package/src/Checkbox/CheckboxInput.jsx +55 -0
  253. package/src/Checkbox/CheckboxInput.native.jsx +6 -0
  254. package/src/Checkbox/index.js +5 -0
  255. package/src/Divider/Divider.jsx +38 -3
  256. package/src/ExpandCollapse/Control.jsx +1 -1
  257. package/src/Feedback/Feedback.jsx +108 -0
  258. package/src/Feedback/index.js +3 -0
  259. package/src/Fieldset/Fieldset.jsx +129 -0
  260. package/src/Fieldset/FieldsetContainer.jsx +22 -0
  261. package/src/Fieldset/FieldsetContainer.native.jsx +16 -0
  262. package/src/Fieldset/Legend.jsx +16 -0
  263. package/src/Fieldset/Legend.native.jsx +22 -0
  264. package/src/Fieldset/cssReset.js +14 -0
  265. package/src/Fieldset/index.js +3 -0
  266. package/src/Icon/Icon.jsx +23 -27
  267. package/src/Icon/IconText.jsx +63 -0
  268. package/src/Icon/index.js +3 -2
  269. package/src/InputLabel/InputLabel.jsx +106 -0
  270. package/src/InputLabel/LabelContent.jsx +13 -0
  271. package/src/InputLabel/LabelContent.native.jsx +6 -0
  272. package/src/InputLabel/index.js +3 -0
  273. package/src/InputSupports/InputSupports.jsx +75 -0
  274. package/src/InputSupports/index.js +3 -0
  275. package/src/InputSupports/propTypes.js +44 -0
  276. package/src/InputSupports/useInputSupports.js +30 -0
  277. package/src/Link/ChevronLink.jsx +28 -7
  278. package/src/Link/InlinePressable.jsx +37 -0
  279. package/src/Link/InlinePressable.native.jsx +73 -0
  280. package/src/Link/Link.jsx +17 -13
  281. package/src/Link/LinkBase.jsx +71 -146
  282. package/src/Link/TextButton.jsx +25 -11
  283. package/src/Link/index.js +2 -1
  284. package/src/List/List.jsx +47 -0
  285. package/src/List/ListItem.jsx +187 -0
  286. package/src/List/index.js +3 -0
  287. package/src/Modal/Modal.jsx +185 -0
  288. package/src/Modal/dictionary.js +9 -0
  289. package/src/Modal/index.js +3 -0
  290. package/src/Notification/Notification.jsx +149 -0
  291. package/src/Notification/dictionary.js +8 -0
  292. package/src/Notification/index.js +3 -0
  293. package/src/Pagination/PageButton.jsx +3 -17
  294. package/src/Pagination/SideButton.jsx +27 -38
  295. package/src/Progress/Progress.jsx +77 -0
  296. package/src/Progress/ProgressBar.jsx +110 -0
  297. package/src/Progress/ProgressBarBackground.jsx +34 -0
  298. package/src/Progress/index.js +6 -0
  299. package/src/Radio/Radio.jsx +233 -0
  300. package/src/Radio/RadioButton.jsx +131 -0
  301. package/src/Radio/RadioGroup.jsx +198 -0
  302. package/src/Radio/RadioInput.jsx +57 -0
  303. package/src/Radio/RadioInput.native.jsx +6 -0
  304. package/src/Radio/index.js +5 -0
  305. package/src/RadioCard/RadioCard.jsx +191 -0
  306. package/src/RadioCard/RadioCardGroup.jsx +211 -0
  307. package/src/RadioCard/index.js +5 -0
  308. package/src/Search/Search.jsx +204 -0
  309. package/src/Search/dictionary.js +12 -0
  310. package/src/Search/index.js +3 -0
  311. package/src/Select/Group.jsx +15 -0
  312. package/src/Select/Group.native.jsx +14 -0
  313. package/src/Select/Item.jsx +11 -0
  314. package/src/Select/Item.native.jsx +10 -0
  315. package/src/Select/Picker.jsx +67 -0
  316. package/src/Select/Picker.native.jsx +95 -0
  317. package/src/Select/Select.jsx +255 -0
  318. package/src/Select/index.js +8 -0
  319. package/src/SideNav/Item.jsx +2 -2
  320. package/src/Skeleton/Skeleton.jsx +98 -0
  321. package/src/Skeleton/index.js +3 -0
  322. package/src/Skeleton/skeleton.constant.js +3 -0
  323. package/src/Skeleton/skeletonWebAnimation.js +13 -0
  324. package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
  325. package/src/Spacer/Spacer.jsx +91 -0
  326. package/src/Spacer/index.js +3 -0
  327. package/src/StackView/StackView.jsx +111 -0
  328. package/src/StackView/StackWrap.jsx +41 -0
  329. package/src/StackView/StackWrap.native.jsx +4 -0
  330. package/src/StackView/StackWrapBox.jsx +94 -0
  331. package/src/StackView/StackWrapGap.jsx +49 -0
  332. package/src/StackView/common.jsx +28 -0
  333. package/src/StackView/getStackedContent.jsx +112 -0
  334. package/src/StackView/index.js +6 -0
  335. package/src/StepTracker/Step.jsx +202 -0
  336. package/src/StepTracker/StepTracker.jsx +163 -0
  337. package/src/StepTracker/dictionary.js +10 -0
  338. package/src/StepTracker/index.js +3 -0
  339. package/src/Tabs/HorizontalScroll.jsx +165 -0
  340. package/src/Tabs/ScrollViewEnd.jsx +53 -0
  341. package/src/Tabs/ScrollViewEnd.native.jsx +24 -0
  342. package/src/Tabs/Tabs.jsx +89 -0
  343. package/src/Tabs/TabsItem.jsx +204 -0
  344. package/src/Tabs/TabsScrollButton.jsx +100 -0
  345. package/src/Tabs/dictionary.js +11 -0
  346. package/src/Tabs/index.js +3 -0
  347. package/src/Tabs/itemPositions.js +101 -0
  348. package/src/Tags/Tags.jsx +207 -0
  349. package/src/Tags/index.js +3 -0
  350. package/src/TextInput/TextArea.jsx +78 -0
  351. package/src/TextInput/TextInput.jsx +52 -0
  352. package/src/TextInput/TextInputBase.jsx +210 -0
  353. package/src/TextInput/index.js +4 -0
  354. package/src/TextInput/propTypes.js +29 -0
  355. package/src/ThemeProvider/useThemeTokens.js +56 -5
  356. package/src/ThemeProvider/utils/styles.js +18 -5
  357. package/src/ThemeProvider/utils/theme-tokens.js +46 -5
  358. package/src/ToggleSwitch/ToggleSwitch.jsx +3 -4
  359. package/src/Tooltip/Backdrop.jsx +60 -0
  360. package/src/Tooltip/Backdrop.native.jsx +33 -0
  361. package/src/Tooltip/Tooltip.jsx +294 -0
  362. package/src/Tooltip/dictionary.js +8 -0
  363. package/src/Tooltip/getTooltipPosition.js +161 -0
  364. package/src/Tooltip/index.js +3 -0
  365. package/src/TooltipButton/TooltipButton.jsx +49 -0
  366. package/src/TooltipButton/index.js +3 -0
  367. package/src/Typography/Typography.jsx +10 -24
  368. package/src/ViewportProvider/ViewportProvider.jsx +21 -0
  369. package/src/ViewportProvider/index.jsx +2 -41
  370. package/src/ViewportProvider/useViewport.js +5 -0
  371. package/src/ViewportProvider/useViewportListener.js +43 -0
  372. package/src/index.js +34 -2
  373. package/src/utils/a11y/index.js +1 -0
  374. package/src/utils/a11y/textSize.js +30 -0
  375. package/src/utils/children.jsx +66 -0
  376. package/src/utils/index.js +11 -1
  377. package/src/utils/info/index.js +8 -0
  378. package/src/utils/info/platform/index.js +11 -0
  379. package/src/utils/info/platform/platform.android.js +1 -0
  380. package/src/utils/info/platform/platform.ios.js +1 -0
  381. package/src/utils/info/platform/platform.js +1 -0
  382. package/src/utils/info/platform/platform.native.js +4 -0
  383. package/src/utils/info/versions.js +6 -0
  384. package/src/utils/input.js +22 -13
  385. package/src/utils/pressability.js +96 -0
  386. package/src/utils/propTypes.js +195 -47
  387. package/src/utils/useCopy.js +39 -0
  388. package/src/utils/useHash.js +34 -0
  389. package/src/utils/useHash.native.js +6 -0
  390. package/src/utils/useResponsiveProp.js +50 -0
  391. package/src/utils/{spacing/useSpacingScale.js → useSpacingScale.js} +25 -10
  392. package/src/utils/useUniqueId.js +14 -0
  393. package/stories/A11yText/A11yText.stories.jsx +15 -13
  394. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +11 -2
  395. package/stories/Box/Box.stories.jsx +29 -2
  396. package/stories/Button/Button.stories.jsx +21 -20
  397. package/stories/Button/ButtonGroup.stories.jsx +2 -1
  398. package/stories/Button/ButtonLink.stories.jsx +6 -4
  399. package/stories/Card/Card.stories.jsx +13 -1
  400. package/stories/Checkbox/Checkbox.stories.jsx +94 -0
  401. package/stories/Divider/Divider.stories.jsx +26 -2
  402. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +74 -79
  403. package/stories/Feedback/Feedback.stories.jsx +96 -0
  404. package/stories/FlexGrid/01 FlexGrid.stories.jsx +20 -7
  405. package/stories/Icon/Icon.stories.jsx +15 -6
  406. package/stories/InputLabel/InputLabel.stories.jsx +42 -0
  407. package/stories/Link/ChevronLink.stories.jsx +20 -4
  408. package/stories/Link/Link.stories.jsx +39 -3
  409. package/stories/Link/TextButton.stories.jsx +24 -2
  410. package/stories/List/List.stories.jsx +117 -0
  411. package/stories/Modal/Modal.stories.jsx +29 -0
  412. package/stories/Notification/Notification.stories.jsx +82 -0
  413. package/stories/Pagination/Pagination.stories.jsx +28 -14
  414. package/stories/Progress/Progress.stories.jsx +93 -0
  415. package/stories/Radio/Radio.stories.jsx +100 -0
  416. package/stories/RadioCard/RadioCard.stories.jsx +98 -0
  417. package/stories/Search/Search.stories.jsx +16 -0
  418. package/stories/Select/Select.stories.jsx +55 -0
  419. package/stories/SideNav/SideNav.stories.jsx +17 -2
  420. package/stories/Skeleton/Skeleton.stories.jsx +36 -0
  421. package/stories/Spacer/Spacer.stories.jsx +38 -0
  422. package/stories/StackView/StackView.stories.jsx +75 -0
  423. package/stories/StackView/StackWrap.stories.jsx +64 -0
  424. package/stories/StepTracker/StepTracker.stories.jsx +71 -0
  425. package/stories/Tabs/Tabs.stories.jsx +97 -0
  426. package/stories/Tags/Tags.stories.jsx +69 -0
  427. package/stories/TextInput/TextArea.stories.jsx +100 -0
  428. package/stories/TextInput/TextInput.stories.jsx +103 -0
  429. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +16 -3
  430. package/stories/Tooltip/Tooltip.stories.jsx +81 -0
  431. package/stories/TooltipButton/TooltipButton.stories.jsx +11 -0
  432. package/stories/Typography/Typography.stories.jsx +12 -3
  433. package/stories/{platform-supports.web.jsx → platform-supports.jsx} +1 -1
  434. package/stories/supports.jsx +110 -14
  435. package/__fixtures__/accessible.icon.svg +0 -6
  436. package/babel.config.json +0 -8
  437. package/lib/ActivityIndicator/Spinner.web.js +0 -55
  438. package/lib/Pagination/useCopy.js +0 -10
  439. package/lib/config/svgr-icons-web.js +0 -9
  440. package/lib/config/svgr-icons.js +0 -52
  441. package/lib/utils/spacing/index.js +0 -2
  442. package/lib/utils/spacing/utils.js +0 -32
  443. package/src/Pagination/useCopy.js +0 -7
  444. package/src/config/svgr-icons-web.js +0 -11
  445. package/src/config/svgr-icons.js +0 -46
  446. package/src/utils/spacing/index.js +0 -3
  447. package/src/utils/spacing/utils.js +0 -28
@@ -0,0 +1,161 @@
1
+ function normalizePosition(position) {
2
+ const { left, right, bottom, top, width, ...rest } = position
3
+
4
+ // adjust the coordinates so that it fits within the window
5
+ const normalized = {
6
+ left: Math.max(0, left),
7
+ right: Math.max(0, right),
8
+ top: Math.max(0, top),
9
+ bottom // since it's ok the make the document grow downwards - no need to normalize here
10
+ }
11
+
12
+ const getAbsoluteDiff = (value1, value2) => Math.abs(Math.abs(value1) - Math.abs(value2))
13
+
14
+ // adjust the width by whatever has been subtracted from left or right
15
+ normalized.width =
16
+ width -
17
+ Math.abs(getAbsoluteDiff(left, normalized.left) - getAbsoluteDiff(right, normalized.right))
18
+
19
+ if (normalized.top !== top) {
20
+ normalized.bottom += normalized.top - top
21
+ }
22
+
23
+ const isNormalized =
24
+ normalized.right !== right || normalized.left !== left || normalized.top !== top
25
+
26
+ return {
27
+ ...normalized,
28
+ ...rest,
29
+ isNormalized
30
+ }
31
+ }
32
+
33
+ function invertPosition(position) {
34
+ switch (position) {
35
+ case 'above':
36
+ return 'below'
37
+ case 'below':
38
+ return 'above'
39
+ case 'left':
40
+ return 'right'
41
+ default:
42
+ return 'left'
43
+ }
44
+ }
45
+
46
+ function findRectByPosition(position, rectsArray) {
47
+ return rectsArray.find(({ position: rectPosition }) => rectPosition === position)
48
+ }
49
+
50
+ /**
51
+ * Used for absolute positioning of the tooltip. Since the tooltip is always centered relatively
52
+ * to the control (button) and we have a limited set of positions, an easy and consistent way
53
+ * of positioning it is to check all of the possible positions and pick one that will be rendered
54
+ * within the window bounds. This way we can also rely on the tooltip being actually rendered
55
+ * before it is shown, which makes it account for the width being limiting in styles, custom font
56
+ * rendering, etc.
57
+ */
58
+ function getTooltipPosition(
59
+ position,
60
+ { controlLayout, tooltipDimensions, windowDimensions, arrowWidth = 0, arrowOffset = 0 }
61
+ ) {
62
+ const { width: controlWidth, height: controlHeight, x: controlX, y: controlY } = controlLayout
63
+ const { width: tooltipWidth, height: tooltipHeight } = tooltipDimensions
64
+ const { width: windowWidth, height: windowHeight } = windowDimensions
65
+
66
+ const arrowSize = arrowWidth / 2 + arrowOffset
67
+
68
+ const horizontalBounds = {
69
+ left: controlX + controlWidth / 2 - tooltipWidth / 2,
70
+ right: windowWidth - (controlX + controlWidth / 2 + tooltipWidth / 2)
71
+ }
72
+
73
+ const verticalBounds = {
74
+ top: controlY + controlHeight / 2 - tooltipHeight / 2,
75
+ bottom: windowHeight - (controlY + controlHeight / 2 + tooltipHeight / 2)
76
+ }
77
+
78
+ // calculate absolute coordinates for each of the potential positions (relative to window)
79
+ const boundingRects = [
80
+ {
81
+ position: 'above',
82
+ ...horizontalBounds,
83
+ top: controlY - tooltipHeight - arrowSize,
84
+ bottom: windowHeight - (controlY - arrowSize)
85
+ },
86
+ {
87
+ position: 'right',
88
+ ...verticalBounds,
89
+ left: controlX + controlWidth + arrowSize,
90
+ right: windowWidth - (controlX + controlWidth + tooltipWidth + arrowSize)
91
+ },
92
+ {
93
+ position: 'below',
94
+ ...horizontalBounds,
95
+ top: controlY + controlHeight + arrowSize,
96
+ bottom: windowHeight - (controlY + controlHeight + tooltipHeight + arrowSize)
97
+ },
98
+ {
99
+ position: 'left',
100
+ ...verticalBounds,
101
+ left: controlX - tooltipWidth - arrowSize,
102
+ right: windowWidth - (controlX - arrowSize)
103
+ }
104
+ ].map((rect) => {
105
+ // an absolute value representing how much of the tooltip is overflowing the window on each side
106
+ const windowOverflow = Math.abs(
107
+ Math.min(rect.top, 0) -
108
+ Math.min(rect.left, 0) -
109
+ Math.min(rect.right, 0) -
110
+ Math.min(rect.bottom, 0)
111
+ )
112
+
113
+ return {
114
+ ...rect,
115
+ ...tooltipDimensions,
116
+ overflow: windowOverflow,
117
+ isNormalized: false
118
+ }
119
+ })
120
+
121
+ // the 'position' prop overrides the automatic positioning
122
+ if (position !== 'auto') {
123
+ let rect = findRectByPosition(position, boundingRects)
124
+
125
+ // check if the suggested 'position' fits in window
126
+ if (rect.overflow === 0) {
127
+ return rect
128
+ }
129
+
130
+ // otherwise try the inverted position (e.g. left -> right)
131
+ rect = findRectByPosition(invertPosition(position), boundingRects)
132
+
133
+ if (rect.overflow === 0) {
134
+ return rect
135
+ }
136
+ }
137
+
138
+ const inWindow = boundingRects.filter(({ overflow }) => overflow === 0)
139
+
140
+ // pick the first position that fits in window
141
+ // (these are sorted clockwise which makes them show where one would expect them to be)
142
+ if (inWindow.length > 0) {
143
+ return inWindow[0]
144
+ }
145
+
146
+ // if all positions would end up being out of window bounds, let's pick the one that is
147
+ // the least overflowing and normalize its position to fit within window bounds
148
+ boundingRects.sort(({ overflow: overflowA }, { overflow: overflowB }) => overflowA - overflowB)
149
+
150
+ const leastOverflowing = boundingRects[0]
151
+
152
+ // prefer 'below' over 'above', since we can always expand the document downwards,
153
+ // and 'above' might cause issues on small viewports with large tooltips
154
+ return normalizePosition(
155
+ leastOverflowing.position === 'above'
156
+ ? findRectByPosition('below', boundingRects)
157
+ : leastOverflowing
158
+ )
159
+ }
160
+
161
+ export default getTooltipPosition
@@ -0,0 +1,3 @@
1
+ import Tooltip from './Tooltip'
2
+
3
+ export default Tooltip
@@ -0,0 +1,49 @@
1
+ import React from 'react'
2
+ import { View } from 'react-native'
3
+
4
+ import PropTypes from 'prop-types'
5
+ import { useThemeTokens, applyOuterBorder } from '../ThemeProvider'
6
+ import { getTokensPropType, variantProp } from '../utils'
7
+ import Icon from '../Icon'
8
+
9
+ const selectInnerContainerStyles = ({ borderRadius, width }) => ({ borderRadius, width })
10
+
11
+ const selectIconTokens = ({ iconSize, iconColor /* iconScale = 1 */ }) => ({
12
+ size: iconSize,
13
+ color: iconColor
14
+ // scale: iconScale TODO re-enable with icon component
15
+ })
16
+
17
+ /**
18
+ * `TooltipButton` is a helper component used as a default control for the `Tooltip` component.
19
+ * In fact though, it isn't actually a pressable - it's meant to be used as pressable's content.
20
+ * Due to this any interaction states (e.g. pressed, hover, etc.) has to be passed down to it as a prop.
21
+ */
22
+ const TooltipButton = ({ pressableState, tokens, variant }) => {
23
+ const themeTokens = useThemeTokens('TooltipButton', tokens, variant, pressableState)
24
+
25
+ const { icon: IconComponent } = themeTokens
26
+
27
+ return (
28
+ <View style={applyOuterBorder(themeTokens)}>
29
+ <View style={selectInnerContainerStyles(themeTokens)}>
30
+ {IconComponent && <Icon icon={IconComponent} tokens={selectIconTokens(themeTokens)} />}
31
+ </View>
32
+ </View>
33
+ )
34
+ }
35
+
36
+ TooltipButton.propTypes = {
37
+ /**
38
+ * Used as appearances when resolving theme tokens.
39
+ */
40
+ pressableState: PropTypes.shape({
41
+ pressed: PropTypes.bool,
42
+ hover: PropTypes.bool,
43
+ focus: PropTypes.bool
44
+ }),
45
+ tokens: getTokensPropType('TooltipButton'),
46
+ variant: variantProp.propType
47
+ }
48
+
49
+ export default TooltipButton
@@ -0,0 +1,3 @@
1
+ import TooltipButton from './TooltipButton'
2
+
3
+ export default TooltipButton
@@ -1,11 +1,11 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { Platform, Text, View } from 'react-native'
3
+ import { Text, View } from 'react-native'
4
4
 
5
5
  import { useThemeTokens } from '../ThemeProvider'
6
6
  import { useViewport } from '../ViewportProvider'
7
7
  import { applyTextStyles } from '../ThemeProvider/utils'
8
- import { a11yProps, variantProp, getTokensPropType } from '../utils/propTypes'
8
+ import { a11yProps, variantProp, getTokensPropType, getMaxFontMultiplier } from '../utils'
9
9
 
10
10
  /**
11
11
  * If passed a string like 'h1', 'h2' etc, returns the heading number as a string,
@@ -16,27 +16,15 @@ function getHeadingLevel(heading) {
16
16
  return match && match[1]
17
17
  }
18
18
 
19
- /**
20
- * Enforces `fontScaleCap` theme tokens as the maximum font size text can become
21
- * after iOS or Android font scaling, to give consistent accessible maximum sizes
22
- * that don't make the content unusable
23
- */
24
- function getMaxFontMultiplier({ fontSize, fontScaleCap }) {
25
- if (!fontScaleCap || !fontSize) return undefined
26
- if (fontScaleCap <= fontSize) return 1
27
- return fontScaleCap / fontSize
28
- }
29
-
30
19
  const selectTextStyles = ({
31
20
  fontWeight,
32
21
  fontSize,
33
22
  color,
34
23
  lineHeight,
35
24
  fontName,
36
- marginTop,
37
- marginBottom,
38
25
  textAlign,
39
- textTransform
26
+ textTransform,
27
+ letterSpacing
40
28
  }) =>
41
29
  applyTextStyles({
42
30
  fontWeight,
@@ -44,10 +32,9 @@ const selectTextStyles = ({
44
32
  color,
45
33
  lineHeight,
46
34
  fontName,
47
- marginTop,
48
- marginBottom,
49
35
  textAlign,
50
- textTransform
36
+ textTransform,
37
+ letterSpacing
51
38
  })
52
39
 
53
40
  // General-purpose flexible theme-neutral base component for text
@@ -64,17 +51,16 @@ const Typography = ({
64
51
  const viewport = useViewport()
65
52
  const themeTokens = useThemeTokens('Typography', tokens, variant, { viewport })
66
53
  const textProps = {
67
- style: selectTextStyles(align ? { ...themeTokens, textAlign: align } : themeTokens)
54
+ style: selectTextStyles(align ? { ...themeTokens, textAlign: align } : themeTokens),
55
+ maxFontSizeMultiplier: getMaxFontMultiplier(themeTokens)
68
56
  }
69
- if (Platform.OS !== 'web') textProps.maxFontSizeMultiplier = getMaxFontMultiplier(themeTokens)
70
57
 
71
58
  const headingLevel = getHeadingLevel(heading)
72
59
  const a11y = {
73
60
  ...a11yProps.select(rest),
74
61
  accessibilityRole,
75
- // On React Native Web, `aria-level` controls which heading tag (h1, h2 etc) is used.
76
- // Must be hyphenated, not camel case; `accessibilityLevel` only works on RNW >=0.15.1
77
- [headingLevel && 'aria-level']: headingLevel
62
+ // On React Native Web, `accessibilityLevel` controls which heading tag (h1, h2 etc) is used.
63
+ ...(headingLevel && { accessibilityLevel: headingLevel })
78
64
  }
79
65
 
80
66
  return block ? (
@@ -0,0 +1,21 @@
1
+ import React, { useState } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { viewports } from '@telus-uds/system-constants'
4
+ import { ViewportContext } from './useViewport'
5
+ import useViewportListener from './useViewportListener'
6
+
7
+ /**
8
+ * Provides an up-to-date viewport value from system-constants, available via the `useViewport` hook
9
+ */
10
+ const ViewportProvider = ({ children }) => {
11
+ // Default to the smallest viewport for mobile-first SSR. On client side, this is updated
12
+ // by useViewportListener in a layout effect before anything is shown to the user.
13
+ const [viewport, setViewport] = useState(viewports.keys[0])
14
+ useViewportListener(setViewport)
15
+ return <ViewportContext.Provider value={viewport}>{children}</ViewportContext.Provider>
16
+ }
17
+ ViewportProvider.propTypes = {
18
+ children: PropTypes.node.isRequired
19
+ }
20
+
21
+ export default ViewportProvider
@@ -1,43 +1,4 @@
1
- import React, { createContext, useState, useEffect, useContext } from 'react'
2
- import PropTypes from 'prop-types'
3
- import { Dimensions } from 'react-native'
4
- import { viewports } from '@telus-uds/system-constants'
5
-
6
- // we are using Dimensions instead of useWindowDimensions
7
- // that's because useWindowDimensions forces context to update on
8
- // every pixel change on the browser, therefore we used Dimension to only enforce
9
- // context update on viewport changes
10
- const lookupViewport = () => viewports.select(Dimensions.get('window').width)
11
-
12
- export const ViewportContext = createContext({})
13
-
14
- /**
15
- * Provides an up-to-date viewport value from system-constants, available via the `useViewport` hook
16
- */
17
- const ViewportProvider = ({ children }) => {
18
- // initialize with a function so we don't re-execute on each render
19
- const [viewport, setViewport] = useState(lookupViewport)
20
-
21
- useEffect(() => {
22
- const onChange = ({ window }) => setViewport(viewports.select(window.width))
23
-
24
- Dimensions.addEventListener('change', onChange)
25
- // We might have missed an update between calling `get` in render and
26
- // `addEventListener` in this handler, so we set it here. If there was
27
- // no change, React will filter out this update as a no-op.
28
- setViewport(lookupViewport())
29
- return () => {
30
- Dimensions.removeEventListener('change', onChange)
31
- }
32
- }, [])
33
-
34
- return <ViewportContext.Provider value={viewport}>{children}</ViewportContext.Provider>
35
- }
36
-
37
- ViewportProvider.propTypes = {
38
- children: PropTypes.node.isRequired
39
- }
1
+ import ViewportProvider from './ViewportProvider'
40
2
 
41
3
  export default ViewportProvider
42
-
43
- export const useViewport = () => useContext(ViewportContext)
4
+ export * from './useViewport'
@@ -0,0 +1,5 @@
1
+ import { createContext, useContext } from 'react'
2
+
3
+ export const ViewportContext = createContext({})
4
+
5
+ export const useViewport = () => useContext(ViewportContext)
@@ -0,0 +1,43 @@
1
+ import { useLayoutEffect } from 'react'
2
+ import { Dimensions } from 'react-native'
3
+ import { viewports } from '@telus-uds/system-constants'
4
+
5
+ // Use Dimensions instead of useWindowDimensions because useWindowDimensions forces context
6
+ // to update on every pixel change during window resize; but we only want rerenders to occur
7
+ // when a viewport threshold has been crossed.
8
+ const lookupViewport = () => viewports.select(Dimensions.get('window').width)
9
+
10
+ /**
11
+ * In SSR, React gets spooked if it sees `useLayoutEffect` and fires warnings assuming the
12
+ * developer doesn't realise the effect won't run: https://reactjs.org/link/uselayouteffect-ssr
13
+ *
14
+ * To avoid these warnings while still conforming to the rules of hooks, always use this
15
+ * explicitly no-op hook, instead of the useLayoutEffect that is implicitly no-op on SSR.
16
+ */
17
+ const useViewportListenerSSR = () => {}
18
+
19
+ /**
20
+ * When client-side rendering, immediately set the viewport to the correct value as a layout effect so
21
+ * if the viewport isn't the smallest, any SSR-rendered components rerender correctly before anything
22
+ * is shown to the user. Then bind events to update the viewport if it changes.
23
+ */
24
+ const useViewportListenerCSR = (setViewport) => {
25
+ useLayoutEffect(() => {
26
+ setViewport(lookupViewport())
27
+
28
+ const onChange = ({ window }) => setViewport(viewports.select(window.width))
29
+ const listener = Dimensions.addEventListener('change', onChange)
30
+
31
+ // From RN 0.65.0, Dimensions.removeEventListener is deprecated for `remove` on addEventListener return value;
32
+ // however, that is not available in RN <=0.64.X, therefore not in any Expo release as of 2021 (Expo SDK 43).
33
+ return listener?.remove || (() => Dimensions.removeEventListener('change', onChange))
34
+
35
+ // setViewport is a function from `useState` so it is stable and won't make the effect re-run
36
+ }, [setViewport])
37
+ }
38
+
39
+ // Window is a defined global object in both Web and Native client-side, and undefined in SSR
40
+ const isSSR = typeof window === 'undefined'
41
+ const useViewportListener = isSSR ? useViewportListenerSSR : useViewportListenerCSR
42
+
43
+ export default useViewportListener
package/src/index.js CHANGED
@@ -1,21 +1,53 @@
1
+ export { default as A11yText } from './A11yText'
1
2
  export { default as ActivityIndicator } from './ActivityIndicator'
2
3
  export { default as Box } from './Box'
3
4
  export * from './Button'
4
- export { default as Card } from './Card'
5
+ export { default as Card, PressableCardBase } from './Card'
6
+ export { default as Checkbox } from './Checkbox'
7
+ export * from './Checkbox'
5
8
  export { default as Divider } from './Divider'
6
9
  export { default as ExpandCollapse, Accordion } from './ExpandCollapse'
10
+ export { default as Feedback } from './Feedback'
11
+ export { default as Fieldset } from './Fieldset'
7
12
  export { default as FlexGrid } from './FlexGrid'
8
13
  export { default as Icon } from './Icon'
9
14
  export * from './Icon'
15
+ export { default as InputLabel } from './InputLabel'
10
16
  export * from './Link'
17
+ export { default as List } from './List'
18
+ export { default as Modal } from './Modal'
19
+ export { default as Notification } from './Notification'
11
20
  export { default as Pagination } from './Pagination'
21
+ export { default as Progress } from './Progress'
22
+ export { default as Radio } from './Radio'
23
+ export * from './Radio'
24
+ export { default as RadioCard } from './RadioCard'
25
+ export * from './RadioCard'
26
+ export { default as Search } from './Search'
27
+ export { default as Select } from './Select'
12
28
  export { default as SideNav } from './SideNav'
29
+ export { default as Skeleton } from './Skeleton'
30
+ export { default as Spacer } from './Spacer'
31
+ export { default as StackView } from './StackView'
32
+ export * from './StackView'
33
+ export { default as StepTracker } from './StepTracker'
34
+ export { default as Tabs } from './Tabs'
35
+ export { default as Tags } from './Tags'
36
+ export * from './TextInput'
13
37
  export { default as ToggleSwitch } from './ToggleSwitch'
38
+ export { default as Tooltip } from './Tooltip'
39
+ export { default as TooltipButton } from './TooltipButton'
14
40
  export { default as Typography } from './Typography'
15
41
 
16
42
  export { default as A11yInfoProvider, useA11yInfo } from './A11yInfoProvider'
17
43
  export { default as BaseProvider } from './BaseProvider'
18
44
  export { default as ViewportProvider, useViewport } from './ViewportProvider'
19
- export { default as ThemeProvider, useTheme, useSetTheme } from './ThemeProvider'
45
+ export {
46
+ default as ThemeProvider,
47
+ useTheme,
48
+ useSetTheme,
49
+ useThemeTokens,
50
+ getThemeTokens
51
+ } from './ThemeProvider'
20
52
 
21
53
  export * from './utils'
@@ -0,0 +1 @@
1
+ export * from './textSize'
@@ -0,0 +1,30 @@
1
+ import { PixelRatio, Platform } from 'react-native'
2
+
3
+ /**
4
+ * When a user increases text size using device accessibility settings, some elements
5
+ * should also scale, such as icons alongside text and space between paragraphs.
6
+ *
7
+ * @param {number} [value] - the value to multiply; defaults to system default font size
8
+ * @param {number} [maxScale] - the maximum multiplier to apply; defaults to no maximum
9
+ */
10
+ export const scaleWithText = (value, maxScale = Infinity) => {
11
+ if (!value) return value
12
+ const scale = Math.min(PixelRatio.getFontScale(), maxScale) || 1
13
+ return value * scale
14
+ }
15
+
16
+ /**
17
+ * Native only, returns `undefined` on Web.
18
+ *
19
+ * Enforces `fontScaleCap` theme tokens as the maximum font size text can become
20
+ * after iOS or Android font scaling, to give consistent accessible maximum sizes
21
+ * that don't make the content unusable.
22
+ *
23
+ * The return value of this function can be used as a React Native `Text` element's
24
+ * `maxFontSizeMultiplier` prop value.
25
+ */
26
+ export const getMaxFontMultiplier = ({ fontSize, fontScaleCap }) => {
27
+ if (Platform.OS === 'web' || !fontScaleCap || !fontSize) return undefined
28
+ if (fontScaleCap <= fontSize) return 1
29
+ return fontScaleCap / fontSize
30
+ }
@@ -0,0 +1,66 @@
1
+ import React, { Children, Fragment } from 'react'
2
+ import { Text } from 'react-native'
3
+
4
+ /**
5
+ * Unpacks top-level fragments, so that common compositional patterns such as the following examples
6
+ * can be iterated as flat siblings (as if they were `<Child1 /><Child2 /><Child3 />`):
7
+ *
8
+ * - Setting `children` as a property wrapped in a fragment:
9
+ *
10
+ * ```jsx
11
+ * args.children = <><Child1 /><Child2 /><Child3 /></>
12
+ * ```
13
+ *
14
+ * - Defining `children` as a variable wrapped in a fragment:
15
+ *
16
+ * ```jsx
17
+ * const content = <><Child1 /><Child2 /><Child3 /></>
18
+ * if (someCondition) return <SomeWrapper>{content}</SomeWrapper>
19
+ * ```
20
+ *
21
+ * - Using fragments at the top level of a JSX block for conditional rendering:
22
+ *
23
+ * ```jsx
24
+ * <Child1 />
25
+ * {someCondition && (
26
+ * <>
27
+ * <Child2 />
28
+ * <Child3 />
29
+ * </>
30
+ * )}
31
+ * ```
32
+ *
33
+ * @param {ReactChildren} child
34
+ * @returns {ReactChildren}
35
+ */
36
+ export const unpackFragment = (child) => {
37
+ // If this level is a set of top-level siblings rather than one child, check each in turn
38
+ if (Children.count(child) > 1) return Children.map(child, unpackFragment)
39
+
40
+ // When a fragment is found, unpack its children to the top level and check them
41
+ if (child?.type === Fragment) return unpackFragment(child.props?.children)
42
+
43
+ // Stop unpacking as soon as any non-fragment child is found
44
+ return child
45
+ }
46
+
47
+ /**
48
+ * React Native on Native crashes if text content is rendered outside `<Text>`, and on web,
49
+ * text style inheritance isn't as expected.
50
+ *
51
+ * Call this function on children that may contain text (strings or numbers) at the top level,
52
+ * and any that are found will be wrapped in a React Native `<Text>` element with supplied props.
53
+ *
54
+ * Note that this does not wrap strings that are nested children of the top level children:
55
+ * `wrapStringsInText(<View>Some text</View>)` will not wrap the inner text and will still crash,
56
+ * but `wrapStringsInText(<>{someString}{anotherString}</>)` will wrap the strings in the fragment.
57
+ *
58
+ * @param {ReactChildren} children
59
+ * @param {TextProps} props
60
+ * @returns {ReactChildren}
61
+ */
62
+ export const wrapStringsInText = (children, props = {}) => {
63
+ return Children.map(unpackFragment(children), (child) =>
64
+ typeof child === 'string' || typeof child === 'number' ? <Text {...props}>{child}</Text> : child
65
+ )
66
+ }
@@ -1,4 +1,14 @@
1
+ export * from './a11y'
1
2
  export * from './animation'
3
+ export * from './children'
2
4
  export * from './input'
5
+ export * from './pressability'
3
6
  export * from './propTypes'
4
- export * from './spacing'
7
+
8
+ export { default as info } from './info'
9
+ export { default as useCopy } from './useCopy'
10
+ export { default as useHash } from './useHash'
11
+ export { default as useSpacingScale } from './useSpacingScale'
12
+ export { default as useResponsiveProp } from './useResponsiveProp'
13
+ export * from './useResponsiveProp'
14
+ export { default as useUniqueId } from './useUniqueId'
@@ -0,0 +1,8 @@
1
+ import platform from './platform'
2
+ import versions from './versions'
3
+
4
+ // export an object accessed like info.platform.OS, info.version.uds, etc
5
+ export default {
6
+ platform,
7
+ versions
8
+ }
@@ -0,0 +1,11 @@
1
+ import { Platform } from 'react-native'
2
+ import fileSuffix from './platform'
3
+
4
+ // Allows consuming libraries that might not have a direct dependency on
5
+ // React Native to check what the current platform is.
6
+
7
+ // Particularly useful for validating Jest config: it is possible for Jest to
8
+ // get configured such that Platform.OS returns a different mocked value to the
9
+ // OS being used to select files by platform suffix (e.g. .web, .native).
10
+
11
+ export default { OS: Platform.OS, fileSuffix }
@@ -0,0 +1 @@
1
+ export default '.android'
@@ -0,0 +1 @@
1
+ export default '.ios'
@@ -0,0 +1 @@
1
+ export default '.web (default)'
@@ -0,0 +1,4 @@
1
+ // This shouldn't ever be chosen, as the more specific '.ios' and '.android' are available.
2
+ // If this gets picked, either an unsupported React Native platform is being used somehow
3
+ // (e.g. a native Windows app), or there's a serious config problem somewhere.
4
+ export default '.native'
@@ -0,0 +1,6 @@
1
+ import pkgJson from '../../../package.json'
2
+
3
+ // Add more versions if they are useful e.g. theme schema version
4
+ export default {
5
+ uds: pkgJson.version
6
+ }