@telus-uds/components-base 0.0.2-prerelease.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. package/.eslintrc.js +9 -0
  2. package/.storybook/main.js +4 -0
  3. package/.storybook/preview.js +37 -0
  4. package/.ultra.cache.json +1 -1
  5. package/CHANGELOG.md +50 -0
  6. package/README.md +4 -2
  7. package/__fixtures__/test-utils.js +25 -0
  8. package/__fixtures__/testTheme.js +4 -2
  9. package/__tests__/Button/ButtonGroup.test.jsx +4 -5
  10. package/__tests__/Checkbox/Checkbox.test.jsx +2 -2
  11. package/__tests__/Checkbox/CheckboxGroup.test.jsx +4 -5
  12. package/__tests__/ExpandCollapse/ExpandCollapse.test.jsx +2 -2
  13. package/__tests__/HorizontalScroll/HorizontalScroll.test.jsx +164 -0
  14. package/__tests__/Link/LinkBase.test.jsx +0 -14
  15. package/__tests__/Radio/Radio.test.jsx +2 -2
  16. package/__tests__/Radio/RadioGroup.test.jsx +4 -5
  17. package/__tests__/RadioCard/RadioCard.test.jsx +2 -2
  18. package/__tests__/RadioCard/RadioCardGroup.test.jsx +4 -5
  19. package/__tests__/Search/Search.test.jsx +9 -8
  20. package/__tests__/Select/Select.test.jsx +3 -2
  21. package/__tests__/Tabs/Tabs.test.jsx +1 -161
  22. package/__tests__/Tags/Tags.test.jsx +4 -5
  23. package/__tests__/TextInput/TextArea.test.jsx +3 -2
  24. package/__tests__/TextInput/TextInputBase.test.jsx +10 -5
  25. package/__tests__/ThemeProvider/ThemeProvider.test.jsx +77 -0
  26. package/__tests__/ThemeProvider/useThemeTokens.test.jsx +9 -5
  27. package/__tests__/ThemeProvider/utils/theme-tokens.test.js +41 -0
  28. package/__tests__/ToggleSwitch/ToggleSwitch.test.jsx +3 -2
  29. package/__tests__/utils/children.test.jsx +128 -0
  30. package/__tests__/utils/input.test.js +1 -1
  31. package/__tests__/utils/semantics.test.jsx +43 -0
  32. package/babel.config.js +9 -16
  33. package/component-docs.json +10313 -0
  34. package/generate-component-docs.js +56 -0
  35. package/lib/A11yText/index.js +10 -5
  36. package/lib/ActivityIndicator/Spinner.js +16 -13
  37. package/lib/ActivityIndicator/Spinner.native.js +12 -8
  38. package/lib/Box/Box.js +103 -8
  39. package/lib/Button/Button.js +9 -8
  40. package/lib/Button/ButtonBase.js +14 -7
  41. package/lib/Button/ButtonGroup.js +25 -10
  42. package/lib/Button/ButtonLink.js +10 -7
  43. package/lib/Card/Card.js +2 -0
  44. package/lib/Card/CardBase.js +13 -5
  45. package/lib/Card/PressableCardBase.js +12 -8
  46. package/lib/Checkbox/Checkbox.js +25 -14
  47. package/lib/Checkbox/CheckboxGroup.js +22 -12
  48. package/lib/Divider/Divider.js +12 -7
  49. package/lib/ExpandCollapse/Accordion.js +10 -4
  50. package/lib/ExpandCollapse/Control.js +12 -6
  51. package/lib/ExpandCollapse/ExpandCollapse.js +10 -5
  52. package/lib/ExpandCollapse/Panel.js +8 -7
  53. package/lib/Feedback/Feedback.js +10 -5
  54. package/lib/Fieldset/Fieldset.js +10 -5
  55. package/lib/Fieldset/FieldsetContainer.js +10 -5
  56. package/lib/Fieldset/FieldsetContainer.native.js +10 -5
  57. package/lib/Fieldset/Legend.js +10 -5
  58. package/lib/Fieldset/Legend.native.js +10 -5
  59. package/lib/FlexGrid/Col/Col.js +8 -5
  60. package/lib/FlexGrid/FlexGrid.js +31 -6
  61. package/lib/FlexGrid/Row/Row.js +12 -5
  62. package/lib/{Tabs → HorizontalScroll}/HorizontalScroll.js +5 -4
  63. package/lib/{Tabs/TabsScrollButton.js → HorizontalScroll/HorizontalScrollButton.js} +14 -8
  64. package/lib/{Tabs → HorizontalScroll}/ScrollViewEnd.js +0 -0
  65. package/lib/{Tabs → HorizontalScroll}/ScrollViewEnd.native.js +0 -0
  66. package/lib/{Tabs → HorizontalScroll}/dictionary.js +0 -0
  67. package/lib/HorizontalScroll/index.js +35 -0
  68. package/lib/{Tabs → HorizontalScroll}/itemPositions.js +0 -0
  69. package/lib/Icon/Icon.js +16 -9
  70. package/lib/Icon/IconText.js +8 -7
  71. package/lib/IconButton/IconButton.js +10 -5
  72. package/lib/InputLabel/InputLabel.js +33 -5
  73. package/lib/InputLabel/LabelContent.js +22 -12
  74. package/lib/InputLabel/LabelContent.native.js +23 -5
  75. package/lib/InputSupports/InputSupports.js +10 -5
  76. package/lib/Link/ChevronLink.js +12 -5
  77. package/lib/Link/InlinePressable.js +10 -4
  78. package/lib/Link/InlinePressable.native.js +5 -4
  79. package/lib/Link/Link.js +12 -5
  80. package/lib/Link/LinkBase.js +12 -5
  81. package/lib/Link/TextButton.js +10 -5
  82. package/lib/List/List.js +6 -6
  83. package/lib/List/ListItem.js +28 -33
  84. package/lib/List/index.js +15 -0
  85. package/lib/Modal/Modal.js +10 -5
  86. package/lib/Notification/Notification.js +21 -5
  87. package/lib/Pagination/PageButton.js +16 -11
  88. package/lib/Pagination/Pagination.js +12 -7
  89. package/lib/Pagination/SideButton.js +12 -7
  90. package/lib/Pagination/usePagination.js +2 -2
  91. package/lib/Progress/Progress.js +10 -5
  92. package/lib/Progress/ProgressBar.js +21 -10
  93. package/lib/Progress/ProgressBarBackground.js +12 -8
  94. package/lib/Radio/Radio.js +14 -13
  95. package/lib/Radio/RadioButton.js +20 -9
  96. package/lib/Radio/RadioGroup.js +24 -13
  97. package/lib/RadioCard/RadioCard.js +14 -10
  98. package/lib/RadioCard/RadioCardGroup.js +13 -12
  99. package/lib/Search/Search.js +29 -18
  100. package/lib/Select/Picker.js +11 -6
  101. package/lib/Select/Picker.native.js +21 -6
  102. package/lib/Select/Select.js +46 -4
  103. package/lib/SideNav/Item.js +10 -5
  104. package/lib/SideNav/ItemsGroup.js +10 -5
  105. package/lib/SideNav/SideNav.js +11 -7
  106. package/lib/Skeleton/Skeleton.js +15 -15
  107. package/lib/Skeleton/skeletonWebAnimation.js +1 -1
  108. package/lib/Spacer/Spacer.js +19 -7
  109. package/lib/StackView/StackView.js +26 -7
  110. package/lib/StackView/StackWrap.js +24 -13
  111. package/lib/StackView/StackWrapBox.js +34 -8
  112. package/lib/StackView/StackWrapGap.js +16 -7
  113. package/lib/StackView/common.js +4 -2
  114. package/lib/StackView/getStackedContent.js +2 -2
  115. package/lib/StepTracker/StepTracker.js +10 -5
  116. package/lib/Tabs/Tabs.js +26 -19
  117. package/lib/Tabs/TabsItem.js +16 -12
  118. package/lib/Tags/Tags.js +27 -11
  119. package/lib/TextInput/TextArea.js +7 -5
  120. package/lib/TextInput/TextInput.js +12 -6
  121. package/lib/TextInput/TextInputBase.js +12 -8
  122. package/lib/ThemeProvider/ThemeProvider.js +14 -10
  123. package/lib/ThemeProvider/useSetTheme.js +6 -1
  124. package/lib/ThemeProvider/utils/styles.js +2 -2
  125. package/lib/ThemeProvider/utils/theme-tokens.js +39 -8
  126. package/lib/ToggleSwitch/ToggleSwitch.js +11 -6
  127. package/lib/Tooltip/Backdrop.js +10 -2
  128. package/lib/Tooltip/Tooltip.js +5 -4
  129. package/lib/Typography/Typography.js +40 -24
  130. package/lib/index.js +36 -1
  131. package/lib/utils/a11y/index.js +13 -0
  132. package/lib/utils/a11y/propTypes.js +61 -0
  133. package/lib/utils/a11y/propTypes.native.js +47 -0
  134. package/lib/utils/a11y/semantics.js +173 -0
  135. package/lib/utils/animation/useVerticalExpandAnimation.js +1 -1
  136. package/lib/utils/children.js +55 -8
  137. package/lib/utils/input.js +27 -17
  138. package/lib/utils/propTypes.js +40 -68
  139. package/lib/utils/useCopy.js +1 -1
  140. package/lib/utils/useHash.js +8 -4
  141. package/lib/utils/useSpacingScale.js +1 -3
  142. package/lib/utils/useUniqueId.js +1 -1
  143. package/package.json +14 -6
  144. package/release-context.json +4 -4
  145. package/src/A11yText/index.jsx +6 -4
  146. package/src/ActivityIndicator/Spinner.jsx +5 -3
  147. package/src/ActivityIndicator/Spinner.native.jsx +5 -3
  148. package/src/Box/Box.jsx +125 -39
  149. package/src/Button/Button.jsx +7 -4
  150. package/src/Button/ButtonBase.jsx +86 -77
  151. package/src/Button/ButtonGroup.jsx +81 -69
  152. package/src/Button/ButtonLink.jsx +18 -13
  153. package/src/Card/Card.jsx +2 -2
  154. package/src/Card/CardBase.jsx +6 -4
  155. package/src/Card/PressableCardBase.jsx +71 -64
  156. package/src/Checkbox/Checkbox.jsx +118 -108
  157. package/src/Checkbox/CheckboxGroup.jsx +72 -62
  158. package/src/Divider/Divider.jsx +7 -4
  159. package/src/ExpandCollapse/Accordion.jsx +3 -2
  160. package/src/ExpandCollapse/Control.jsx +40 -43
  161. package/src/ExpandCollapse/ExpandCollapse.jsx +26 -23
  162. package/src/ExpandCollapse/Panel.jsx +69 -63
  163. package/src/Feedback/Feedback.jsx +36 -33
  164. package/src/Fieldset/Fieldset.jsx +63 -56
  165. package/src/Fieldset/FieldsetContainer.jsx +14 -5
  166. package/src/Fieldset/FieldsetContainer.native.jsx +7 -4
  167. package/src/Fieldset/Legend.jsx +7 -2
  168. package/src/Fieldset/Legend.native.jsx +7 -2
  169. package/src/FlexGrid/Col/Col.jsx +139 -132
  170. package/src/FlexGrid/FlexGrid.jsx +79 -51
  171. package/src/FlexGrid/Row/Row.jsx +55 -48
  172. package/src/HorizontalScroll/HorizontalScroll.jsx +168 -0
  173. package/src/HorizontalScroll/HorizontalScrollButton.jsx +105 -0
  174. package/src/{Tabs → HorizontalScroll}/ScrollViewEnd.jsx +0 -0
  175. package/src/{Tabs → HorizontalScroll}/ScrollViewEnd.native.jsx +0 -0
  176. package/src/{Tabs → HorizontalScroll}/dictionary.js +0 -0
  177. package/src/HorizontalScroll/index.js +17 -0
  178. package/src/{Tabs → HorizontalScroll}/itemPositions.js +0 -0
  179. package/src/Icon/Icon.jsx +37 -35
  180. package/src/Icon/IconText.jsx +22 -17
  181. package/src/IconButton/IconButton.jsx +49 -42
  182. package/src/InputLabel/InputLabel.jsx +53 -38
  183. package/src/InputLabel/LabelContent.jsx +14 -6
  184. package/src/InputLabel/LabelContent.native.jsx +11 -2
  185. package/src/InputSupports/InputSupports.jsx +29 -34
  186. package/src/Link/ChevronLink.jsx +26 -16
  187. package/src/Link/InlinePressable.jsx +5 -3
  188. package/src/Link/InlinePressable.native.jsx +5 -3
  189. package/src/Link/Link.jsx +22 -16
  190. package/src/Link/LinkBase.jsx +67 -58
  191. package/src/Link/TextButton.jsx +30 -23
  192. package/src/List/List.jsx +6 -7
  193. package/src/List/ListItem.jsx +70 -90
  194. package/src/List/index.js +5 -0
  195. package/src/Modal/Modal.jsx +9 -4
  196. package/src/Notification/Notification.jsx +58 -43
  197. package/src/Pagination/PageButton.jsx +37 -34
  198. package/src/Pagination/Pagination.jsx +88 -92
  199. package/src/Pagination/SideButton.jsx +44 -41
  200. package/src/Progress/Progress.jsx +5 -4
  201. package/src/Progress/ProgressBar.jsx +42 -29
  202. package/src/Progress/ProgressBarBackground.jsx +5 -3
  203. package/src/Radio/Radio.jsx +85 -78
  204. package/src/Radio/RadioButton.jsx +54 -43
  205. package/src/Radio/RadioGroup.jsx +74 -63
  206. package/src/RadioCard/RadioCard.jsx +75 -68
  207. package/src/RadioCard/RadioCardGroup.jsx +82 -75
  208. package/src/Search/Search.jsx +127 -106
  209. package/src/Select/Picker.jsx +49 -42
  210. package/src/Select/Picker.native.jsx +56 -49
  211. package/src/Select/Select.jsx +115 -72
  212. package/src/SideNav/Item.jsx +53 -46
  213. package/src/SideNav/ItemsGroup.jsx +50 -43
  214. package/src/SideNav/SideNav.jsx +68 -60
  215. package/src/Skeleton/Skeleton.jsx +9 -13
  216. package/src/Spacer/Spacer.jsx +11 -4
  217. package/src/StackView/StackView.jsx +47 -23
  218. package/src/StackView/StackWrap.jsx +14 -12
  219. package/src/StackView/StackWrapBox.jsx +62 -28
  220. package/src/StackView/StackWrapGap.jsx +46 -24
  221. package/src/StackView/common.jsx +3 -2
  222. package/src/StepTracker/StepTracker.jsx +73 -62
  223. package/src/Tabs/Tabs.jsx +70 -62
  224. package/src/Tabs/TabsItem.jsx +111 -103
  225. package/src/Tags/Tags.jsx +114 -102
  226. package/src/TextInput/TextArea.jsx +5 -4
  227. package/src/TextInput/TextInput.jsx +5 -4
  228. package/src/TextInput/TextInputBase.jsx +84 -77
  229. package/src/ThemeProvider/ThemeProvider.jsx +11 -7
  230. package/src/ThemeProvider/useSetTheme.js +4 -0
  231. package/src/ThemeProvider/utils/theme-tokens.js +28 -0
  232. package/src/ToggleSwitch/ToggleSwitch.jsx +49 -50
  233. package/src/Tooltip/Tooltip.jsx +134 -130
  234. package/src/Typography/Typography.jsx +67 -44
  235. package/src/index.js +3 -1
  236. package/src/utils/a11y/index.js +1 -0
  237. package/src/utils/a11y/propTypes.js +61 -0
  238. package/src/utils/a11y/propTypes.native.js +39 -0
  239. package/src/utils/a11y/semantics.js +162 -0
  240. package/src/utils/children.jsx +60 -7
  241. package/src/utils/input.js +20 -17
  242. package/src/utils/propTypes.js +30 -76
  243. package/src/utils/useCopy.js +1 -1
  244. package/src/utils/useHash.js +8 -3
  245. package/stories/A11yText/A11yText.stories.jsx +3 -3
  246. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +2 -2
  247. package/stories/Box/Box.stories.jsx +2 -2
  248. package/stories/Button/Button.stories.jsx +3 -3
  249. package/stories/Button/ButtonGroup.stories.jsx +2 -2
  250. package/stories/Button/ButtonLink.stories.jsx +2 -2
  251. package/stories/Card/Card.stories.jsx +2 -2
  252. package/stories/Checkbox/Checkbox.stories.jsx +2 -2
  253. package/stories/Divider/Divider.stories.jsx +2 -2
  254. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +3 -3
  255. package/stories/Feedback/Feedback.stories.jsx +2 -2
  256. package/stories/FlexGrid/01 FlexGrid.stories.jsx +2 -2
  257. package/stories/FlexGrid/02 Row.stories.jsx +2 -2
  258. package/stories/FlexGrid/03 Col.stories.jsx +2 -2
  259. package/stories/Icon/Icon.stories.jsx +2 -2
  260. package/stories/IconButton/IconButton.stories.jsx +2 -2
  261. package/stories/InputLabel/InputLabel.stories.jsx +2 -2
  262. package/stories/Link/ChevronLink.stories.jsx +2 -2
  263. package/stories/Link/Link.stories.jsx +2 -2
  264. package/stories/Link/TextButton.stories.jsx +2 -2
  265. package/stories/List/List.stories.jsx +2 -2
  266. package/stories/Modal/Modal.stories.jsx +2 -2
  267. package/stories/Notification/Notification.stories.jsx +2 -2
  268. package/stories/Pagination/Pagination.stories.jsx +2 -2
  269. package/stories/Progress/Progress.stories.jsx +2 -2
  270. package/stories/Radio/Radio.stories.jsx +2 -2
  271. package/stories/RadioCard/RadioCard.stories.jsx +2 -2
  272. package/stories/Search/Search.stories.jsx +2 -2
  273. package/stories/Select/Select.stories.jsx +2 -2
  274. package/stories/SideNav/SideNav.stories.jsx +2 -2
  275. package/stories/SideNav/SideNavItem.stories.jsx +2 -2
  276. package/stories/SideNav/SideNavItemsGroup.stories.jsx +2 -2
  277. package/stories/Skeleton/Skeleton.stories.jsx +3 -3
  278. package/stories/Spacer/Spacer.stories.jsx +2 -2
  279. package/stories/StackView/StackView.stories.jsx +2 -2
  280. package/stories/StackView/StackWrap.stories.jsx +2 -2
  281. package/stories/StepTracker/StepTracker.stories.jsx +2 -2
  282. package/stories/Tabs/Tabs.stories.jsx +2 -2
  283. package/stories/Tags/Tags.stories.jsx +2 -2
  284. package/stories/TextInput/TextArea.stories.jsx +2 -2
  285. package/stories/TextInput/TextInput.stories.jsx +2 -2
  286. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +2 -2
  287. package/stories/Tooltip/Tooltip.stories.jsx +2 -2
  288. package/stories/TooltipButton/TooltipButton.stories.jsx +2 -2
  289. package/stories/Typography/Typography.stories.jsx +2 -2
  290. package/stories/platform-supports.jsx +1 -1
  291. package/stories/supports.jsx +4 -5
  292. package/src/Tabs/HorizontalScroll.jsx +0 -165
  293. package/src/Tabs/TabsScrollButton.jsx +0 -100
@@ -1,13 +1,21 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
- function LabelContent({ children, forId }) {
5
- return <label htmlFor={forId}>{children}</label>
6
- }
7
-
8
- export default LabelContent
4
+ const LabelContent = forwardRef(({ children, forId }, ref) => (
5
+ <label ref={ref} htmlFor={forId} style={staticStyles.inheritCursor}>
6
+ {children}
7
+ </label>
8
+ ))
9
+ LabelContent.displayName = 'LabelContent'
9
10
 
10
11
  LabelContent.propTypes = {
11
12
  children: PropTypes.string,
12
13
  forId: PropTypes.string
13
14
  }
15
+
16
+ // Note that <label> is not React Native, so we can't use `StyleSheet.create` here
17
+ const staticStyles = {
18
+ inheritCursor: { cursor: 'inherit' }
19
+ }
20
+
21
+ export default LabelContent
@@ -1,6 +1,15 @@
1
+ import React, { forwardRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { View } from 'react-native'
4
+
1
5
  // Since there's no equivalent for web's <label> element we're simply rendering whatever is passed to this component.
2
- function LabelContent({ children }) {
3
- return children
6
+ const LabelContent = forwardRef(({ children }, ref) =>
7
+ ref ? <View ref={ref}>{children}</View> : children
8
+ )
9
+ LabelContent.displayName = 'LabelContent'
10
+
11
+ LabelContent.propTypes = {
12
+ children: PropTypes.node
4
13
  }
5
14
 
6
15
  export default LabelContent
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
 
3
3
  import PropTypes from 'prop-types'
4
4
  import InputLabel from '../InputLabel'
@@ -7,41 +7,36 @@ import StackView from '../StackView'
7
7
  import { useThemeTokens } from '../ThemeProvider'
8
8
  import useInputSupports from './useInputSupports'
9
9
 
10
- function InputSupports({
11
- children,
12
- label,
13
- hint,
14
- hintPosition = 'inline',
15
- feedback,
16
- tooltip,
17
- validation
18
- }) {
19
- const { space } = useThemeTokens('InputSupports')
10
+ const InputSupports = forwardRef(
11
+ ({ children, label, hint, hintPosition = 'inline', feedback, tooltip, validation }, ref) => {
12
+ const { space } = useThemeTokens('InputSupports')
20
13
 
21
- const { inputId, hintId, feedbackId, a11yProps } = useInputSupports({
22
- feedback,
23
- hint,
24
- label,
25
- validation
26
- })
14
+ const { inputId, hintId, feedbackId, a11yProps } = useInputSupports({
15
+ feedback,
16
+ hint,
17
+ label,
18
+ validation
19
+ })
27
20
 
28
- return (
29
- <StackView space={space}>
30
- {label && (
31
- <InputLabel
32
- label={label}
33
- hint={hint}
34
- hintPosition={hintPosition}
35
- hintId={hintId}
36
- tooltip={tooltip}
37
- forId={inputId}
38
- />
39
- )}
40
- {typeof children === 'function' ? children({ a11yProps, inputId }) : children}
41
- {feedback && <Feedback id={feedbackId} title={feedback} validation={validation} />}
42
- </StackView>
43
- )
44
- }
21
+ return (
22
+ <StackView space={space} ref={ref}>
23
+ {label && (
24
+ <InputLabel
25
+ label={label}
26
+ hint={hint}
27
+ hintPosition={hintPosition}
28
+ hintId={hintId}
29
+ tooltip={tooltip}
30
+ forId={inputId}
31
+ />
32
+ )}
33
+ {typeof children === 'function' ? children({ a11yProps, inputId }) : children}
34
+ {feedback && <Feedback id={feedbackId} title={feedback} validation={validation} />}
35
+ </StackView>
36
+ )
37
+ }
38
+ )
39
+ InputSupports.displayName = 'InputSupports'
45
40
 
46
41
  InputSupports.propTypes = {
47
42
  children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
4
  import { useThemeTokensCallback } from '../ThemeProvider'
@@ -11,24 +11,34 @@ import LinkBase from './LinkBase'
11
11
  *
12
12
  * ChevronLink is not intended to be deeply themable; variants passed to ChevronLink are forwarded to Link.
13
13
  */
14
- const ChevronLink = ({ direction = 'right', children, tokens, variant, ...linkProps }) => {
15
- const getChevronTokens = useThemeTokensCallback('ChevronLink', tokens, variant)
16
- const applyChevronTokens = (linkState) => {
17
- const { leftIcon, rightIcon, iconDisplace, ...otherTokens } = getChevronTokens(linkState)
18
- return {
19
- ...selectTokens('Link', otherTokens),
20
- icon: direction === 'right' ? rightIcon : leftIcon,
21
- iconTranslateX: iconDisplace * (direction === 'right' ? 1 : -1) || 0
14
+ const ChevronLink = forwardRef(
15
+ ({ direction = 'right', children, tokens, variant, dataSet, ...linkProps }, ref) => {
16
+ const getChevronTokens = useThemeTokensCallback('ChevronLink', tokens, variant)
17
+ const applyChevronTokens = (linkState) => {
18
+ const { leftIcon, rightIcon, iconDisplace, ...otherTokens } = getChevronTokens(linkState)
19
+ return {
20
+ ...selectTokens('Link', otherTokens),
21
+ icon: direction === 'right' ? rightIcon : leftIcon,
22
+ iconTranslateX: iconDisplace * (direction === 'right' ? 1 : -1) || 0
23
+ }
22
24
  }
25
+
26
+ const getTokens = useThemeTokensCallback('Link', applyChevronTokens, variant)
27
+ return (
28
+ <LinkBase
29
+ {...linkProps}
30
+ iconPosition={direction}
31
+ tokens={getTokens}
32
+ dataSet={dataSet}
33
+ ref={ref}
34
+ >
35
+ {children}
36
+ </LinkBase>
37
+ )
23
38
  }
39
+ )
24
40
 
25
- const getTokens = useThemeTokensCallback('Link', applyChevronTokens, variant)
26
- return (
27
- <LinkBase {...linkProps} iconPosition={direction} tokens={getTokens}>
28
- {children}
29
- </LinkBase>
30
- )
31
- }
41
+ ChevronLink.displayName = 'ChevronLink'
32
42
  ChevronLink.propTypes = {
33
43
  ...LinkBase.propTypes,
34
44
  tokens: getTokensPropType('ChevronLink', 'Link'),
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import { Pressable, StyleSheet } from 'react-native'
3
3
 
4
4
  /**
@@ -15,8 +15,9 @@ import { Pressable, StyleSheet } from 'react-native'
15
15
  */
16
16
  // React Native exports prop Types but not propTypes, use JSDoc types here rather than duplicate RN
17
17
  // eslint-disable-next-line react/prop-types
18
- const InlinePressable = ({ children, style, ...props }) => (
18
+ const InlinePressable = forwardRef(({ children, style, ...props }, ref) => (
19
19
  <Pressable
20
+ ref={ref}
20
21
  style={(pressState) => [
21
22
  staticStyles.inline,
22
23
  typeof style === 'function' ? style(pressState) : style
@@ -25,7 +26,8 @@ const InlinePressable = ({ children, style, ...props }) => (
25
26
  >
26
27
  {(pressState) => (typeof children === 'function' ? children(pressState) : children)}
27
28
  </Pressable>
28
- )
29
+ ))
30
+ InlinePressable.displayName = 'InlinePressable'
29
31
 
30
32
  const staticStyles = StyleSheet.create({
31
33
  inline: {
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable camelcase */
2
- import React, { useState } from 'react'
2
+ import React, { forwardRef, useState } from 'react'
3
3
  import { Text, TouchableWithoutFeedback } from 'react-native'
4
4
 
5
5
  /**
@@ -38,7 +38,7 @@ const pressablePropsToTouchable = ({
38
38
  */
39
39
  // React Native exports prop Types but not propTypes, use JSDoc types here rather than duplicate RN
40
40
  // eslint-disable-next-line react/prop-types
41
- const InlinePressable = ({ onPress, children, style, ...rest }) => {
41
+ const InlinePressable = forwardRef(({ onPress, children, style, ...rest }, ref) => {
42
42
  const [isFocused, setIsFocused] = useState(false)
43
43
  const handleFocus = () => setIsFocused(true)
44
44
  const handleBlur = () => setIsFocused(false)
@@ -61,6 +61,7 @@ const InlinePressable = ({ onPress, children, style, ...rest }) => {
61
61
  onPressOut={handlePressOut}
62
62
  onFocus={handleFocus}
63
63
  onBlur={handleBlur}
64
+ ref={ref}
64
65
  {...pressablePropsToTouchable(rest)}
65
66
  >
66
67
  <Text style={currentStyle}>
@@ -68,6 +69,7 @@ const InlinePressable = ({ onPress, children, style, ...rest }) => {
68
69
  </Text>
69
70
  </TouchableWithoutFeedback>
70
71
  )
71
- }
72
+ })
73
+ InlinePressable.displayName = 'InlinePressable'
72
74
 
73
75
  export default InlinePressable
package/src/Link/Link.jsx CHANGED
@@ -1,23 +1,29 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
 
3
3
  import { useThemeTokensCallback } from '../ThemeProvider'
4
4
  import LinkBase from './LinkBase'
5
5
 
6
- const Link = ({
7
- href,
8
- children,
9
- accessibilityRole = 'link',
10
- variant = {},
11
- tokens,
12
- ...linkProps
13
- }) => {
14
- const getTokens = useThemeTokensCallback('Link', tokens, variant)
15
- return (
16
- <LinkBase href={href} accessibilityRole={accessibilityRole} tokens={getTokens} {...linkProps}>
17
- {children}
18
- </LinkBase>
19
- )
20
- }
6
+ const Link = forwardRef(
7
+ (
8
+ { href, children, accessibilityRole = 'link', variant = {}, tokens, dataSet, ...linkProps },
9
+ ref
10
+ ) => {
11
+ const getTokens = useThemeTokensCallback('Link', tokens, variant)
12
+ return (
13
+ <LinkBase
14
+ href={href}
15
+ accessibilityRole={accessibilityRole}
16
+ tokens={getTokens}
17
+ ref={ref}
18
+ dataSet={dataSet}
19
+ {...linkProps}
20
+ >
21
+ {children}
22
+ </LinkBase>
23
+ )
24
+ }
25
+ )
26
+ Link.displayName = 'Link'
21
27
 
22
28
  Link.propTypes = LinkBase.propTypes
23
29
 
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { Text, Platform, StyleSheet } from 'react-native'
4
4
  import {
@@ -88,69 +88,78 @@ const selectIconTokens = ({ color, iconSize, iconTranslateX, iconTranslateY }) =
88
88
  * dropped in favour of investigating if a full-featured CSS-in-JS package could or
89
89
  * should be used more widely (e.g. styled components)
90
90
  */
91
- const LinkBase = ({
92
- href,
93
- onPress,
94
- icon,
95
- iconPosition = icon ? 'left' : undefined,
96
- iconProps,
97
- variant,
98
- tokens = {},
99
- children,
100
- accessibilityRole = 'link',
101
- ...props
102
- }) => {
103
- const { hrefAttrs, rest } = hrefAttrsProp.bundle(props)
104
- const linkPropSet = linkProps.select({
105
- accessibilityRole,
106
- href,
107
- onPress: linkProps.handleHref({ href, onPress }),
108
- hrefAttrs,
109
- ...rest
110
- })
91
+ const LinkBase = forwardRef(
92
+ (
93
+ {
94
+ href,
95
+ onPress,
96
+ icon,
97
+ iconPosition = icon ? 'left' : undefined,
98
+ iconProps,
99
+ variant,
100
+ tokens = {},
101
+ children,
102
+ accessibilityRole = 'link',
103
+ dataSet,
104
+ ...props
105
+ },
106
+ ref
107
+ ) => {
108
+ const { hrefAttrs, rest } = hrefAttrsProp.bundle(props)
109
+ const linkPropSet = linkProps.select({
110
+ accessibilityRole,
111
+ href,
112
+ onPress: linkProps.handleHref({ href, onPress }),
113
+ hrefAttrs,
114
+ ...rest
115
+ })
111
116
 
112
- const resolveLinkTokens = (pressState) =>
113
- resolvePressableTokens(tokens, pressState, { iconPosition })
117
+ const resolveLinkTokens = (pressState) =>
118
+ resolvePressableTokens(tokens, pressState, { iconPosition })
114
119
 
115
- // On web, this makes focus rings wrap only the link, not the entire block
116
- const blockLeftStyle = Platform.OS === 'web' && staticStyles.blockLeft
120
+ // On web, this makes focus rings wrap only the link, not the entire block
121
+ const blockLeftStyle = Platform.OS === 'web' && staticStyles.blockLeft
117
122
 
118
- return (
119
- <InlinePressable
120
- {...linkPropSet}
121
- style={(linkState) => {
122
- const themeTokens = resolveLinkTokens(linkState)
123
- const outerBorderStyles = selectOuterBorderStyles(themeTokens)
124
- const hasIcon = Boolean(icon || themeTokens.icon)
125
- return [outerBorderStyles, blockLeftStyle, hasIcon && staticStyles.rowContainer]
126
- }}
127
- >
128
- {(linkState) => {
129
- const themeTokens = resolveLinkTokens(linkState)
130
- const textStyles = selectTextStyles(themeTokens)
131
- const iconTokens = selectIconTokens(themeTokens)
123
+ return (
124
+ <InlinePressable
125
+ {...linkPropSet}
126
+ ref={ref}
127
+ dataSet={dataSet}
128
+ style={(linkState) => {
129
+ const themeTokens = resolveLinkTokens(linkState)
130
+ const outerBorderStyles = selectOuterBorderStyles(themeTokens)
131
+ const hasIcon = Boolean(icon || themeTokens.icon)
132
+ return [outerBorderStyles, blockLeftStyle, hasIcon && staticStyles.rowContainer]
133
+ }}
134
+ >
135
+ {(linkState) => {
136
+ const themeTokens = resolveLinkTokens(linkState)
137
+ const textStyles = selectTextStyles(themeTokens)
138
+ const iconTokens = selectIconTokens(themeTokens)
132
139
 
133
- // TODO: may need to apply some smarter text inheritance here if inline to avoid native
134
- // issues like double-application of line heights breaking align-items: baseline
135
- const blockTextStyles = selectBlockStyles(themeTokens)
140
+ // TODO: may need to apply some smarter text inheritance here if inline to avoid native
141
+ // issues like double-application of line heights breaking align-items: baseline
142
+ const blockTextStyles = selectBlockStyles(themeTokens)
136
143
 
137
- const IconComponent = icon || themeTokens.icon
138
- const { iconSpace } = themeTokens
144
+ const IconComponent = icon || themeTokens.icon
145
+ const { iconSpace } = themeTokens
139
146
 
140
- return (
141
- <IconText
142
- icon={IconComponent}
143
- iconPosition={iconPosition}
144
- space={iconSpace}
145
- iconProps={{ ...iconProps, tokens: iconTokens }}
146
- >
147
- <Text style={[textStyles, blockTextStyles, staticStyles.baseline]}>{children}</Text>
148
- </IconText>
149
- )
150
- }}
151
- </InlinePressable>
152
- )
153
- }
147
+ return (
148
+ <IconText
149
+ icon={IconComponent}
150
+ iconPosition={iconPosition}
151
+ space={iconSpace}
152
+ iconProps={{ ...iconProps, tokens: iconTokens }}
153
+ >
154
+ <Text style={[textStyles, blockTextStyles, staticStyles.baseline]}>{children}</Text>
155
+ </IconText>
156
+ )
157
+ }}
158
+ </InlinePressable>
159
+ )
160
+ }
161
+ )
162
+ LinkBase.displayName = 'LinkBase'
154
163
 
155
164
  LinkBase.propTypes = {
156
165
  ...a11yProps.types,
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
4
  import { useThemeTokensCallback } from '../ThemeProvider'
@@ -9,28 +9,35 @@ import LinkBase from './LinkBase'
9
9
  * Link but has the accessibility role of a `Button`. It should be used for actions that
10
10
  * take place on the current page, or for navigation within an app.
11
11
  */
12
- const TextButton = ({
13
- onPress,
14
- children,
15
- variant,
16
- tokens,
17
- // TODO: this may need to use `link` role on Web in the case of being passed both `href` and
18
- // `onPress` in an omniplatform app that uses React Navigation's useLinkProps for internal nav.
19
- accessibilityRole = 'button',
20
- ...linkProps
21
- }) => {
22
- const getTokens = useThemeTokensCallback('Link', tokens, variant)
23
- return (
24
- <LinkBase
25
- onPress={onPress}
26
- accessibilityRole={accessibilityRole}
27
- tokens={getTokens}
28
- {...linkProps}
29
- >
30
- {children}
31
- </LinkBase>
32
- )
33
- }
12
+ const TextButton = forwardRef(
13
+ (
14
+ {
15
+ onPress,
16
+ children,
17
+ variant,
18
+ tokens,
19
+ // TODO: this may need to use `link` role on Web in the case of being passed both `href` and
20
+ // `onPress` in an omniplatform app that uses React Navigation's useLinkProps for internal nav.
21
+ accessibilityRole = 'button',
22
+ ...linkProps
23
+ },
24
+ ref
25
+ ) => {
26
+ const getTokens = useThemeTokensCallback('Link', tokens, variant)
27
+ return (
28
+ <LinkBase
29
+ onPress={onPress}
30
+ accessibilityRole={accessibilityRole}
31
+ tokens={getTokens}
32
+ ref={ref}
33
+ {...linkProps}
34
+ >
35
+ {children}
36
+ </LinkBase>
37
+ )
38
+ }
39
+ )
40
+ TextButton.displayName = 'TextButton'
34
41
 
35
42
  TextButton.propTypes = {
36
43
  ...LinkBase.propTypes,
package/src/List/List.jsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, { cloneElement, Children } from 'react'
1
+ import React, { cloneElement, forwardRef, Children } from 'react'
2
2
  import { View, Platform } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
4
  import { getTokensPropType, variantProp, componentPropType } from '../utils'
@@ -6,10 +6,10 @@ import { a11yProps } from '../utils/propTypes'
6
6
  import ListItem from './ListItem'
7
7
 
8
8
  /**
9
- * A Unordered List component has a child a ListItem that
9
+ * An unordered List component has a child a ListItem that
10
10
  * allows icon, dividers and customized typography
11
11
  */
12
- const List = ({ children, showDivider, tokens, variant, ...rest }) => {
12
+ const List = forwardRef(({ children, showDivider, tokens, variant, ...rest }, ref) => {
13
13
  const accessibilityRole = Platform.select({ web: 'list', default: 'none' })
14
14
  const a11y = a11yProps.select(rest)
15
15
  const items = Children.map(children, (child, index) => {
@@ -25,13 +25,12 @@ const List = ({ children, showDivider, tokens, variant, ...rest }) => {
25
25
  })
26
26
 
27
27
  return (
28
- <View accessibilityRole={accessibilityRole} {...a11y}>
28
+ <View ref={ref} accessibilityRole={accessibilityRole} {...a11y}>
29
29
  {items}
30
30
  </View>
31
31
  )
32
- }
33
-
34
- List.Item = ListItem
32
+ })
33
+ List.displayName = 'List'
35
34
 
36
35
  List.propTypes = {
37
36
  ...a11yProps.types,