@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,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { Pressable, Platform } from 'react-native'
4
4
 
@@ -33,74 +33,81 @@ export const selectPressableCardTokens = (tokens) =>
33
33
  * based on these to an outer border and a base Card component. Not intended to be used in
34
34
  * apps or sites directly: build themed components on top of this.
35
35
  */
36
- const PressableCardBase = ({
37
- children,
38
- tokens,
39
- checked,
40
- validation,
41
- inactive,
42
- href,
43
- hrefAttrs,
44
- onPress,
45
- accessibilityRole = href ? 'link' : undefined,
46
- ...rest
47
- }) => {
48
- const viewport = useViewport()
49
- const a11y = a11yProps.select({
50
- ...rest,
51
- accessibilityRole
52
- })
53
- const additionalState = { checked, validation, inactive, viewport }
36
+ const PressableCardBase = forwardRef(
37
+ (
38
+ {
39
+ children,
40
+ tokens,
41
+ checked,
42
+ validation,
43
+ inactive,
44
+ href,
45
+ hrefAttrs,
46
+ onPress,
47
+ accessibilityRole = href ? 'link' : undefined,
48
+ ...rest
49
+ },
50
+ ref
51
+ ) => {
52
+ const viewport = useViewport()
53
+ const a11y = a11yProps.select({
54
+ ...rest,
55
+ accessibilityRole
56
+ })
57
+ const additionalState = { checked, validation, inactive, viewport }
54
58
 
55
- const getCardState = (pressableState) => resolvePressableState(pressableState, additionalState)
56
- const getTokens = (pressableState) =>
57
- validateThemeTokens(
58
- resolvePressableTokens(tokens, pressableState, additionalState),
59
- getTokensSetPropType(tokenKeys, { requireAll: true }),
60
- 'PressableCard'
61
- )
59
+ const getCardState = (pressableState) => resolvePressableState(pressableState, additionalState)
60
+ const getTokens = (pressableState) =>
61
+ validateThemeTokens(
62
+ resolvePressableTokens(tokens, pressableState, additionalState),
63
+ getTokensSetPropType(tokenKeys, { requireAll: true }),
64
+ 'PressableCard'
65
+ )
62
66
 
63
- const getCardTokens = (pressableState) => selectTokens('Card', getTokens(pressableState))
64
- const getOuterBorderStyle = (pressableState) => {
65
- const {
66
- flex,
67
- minWidth,
68
- outerBorderColor,
69
- outerBorderGap = 0,
70
- outerBorderWidth = 0,
71
- borderRadius
72
- } = getTokens(pressableState)
73
- return {
74
- flex,
75
- minWidth: minWidth + outerBorderGap + outerBorderWidth,
76
- ...applyOuterBorder({ outerBorderColor, outerBorderGap, outerBorderWidth, borderRadius }),
77
- ...Platform.select({ web: { outline: 'none' } })
67
+ const getCardTokens = (pressableState) => selectTokens('Card', getTokens(pressableState))
68
+ const getOuterBorderStyle = (pressableState) => {
69
+ const {
70
+ flex,
71
+ minWidth,
72
+ outerBorderColor,
73
+ outerBorderGap = 0,
74
+ outerBorderWidth = 0,
75
+ borderRadius
76
+ } = getTokens(pressableState)
77
+ return {
78
+ flex,
79
+ minWidth: minWidth + outerBorderGap + outerBorderWidth,
80
+ ...applyOuterBorder({ outerBorderColor, outerBorderGap, outerBorderWidth, borderRadius }),
81
+ ...Platform.select({ web: { outline: 'none' } })
82
+ }
78
83
  }
79
- }
80
84
 
81
- const handleChange = linkProps.handleHref({ href, onPress })
82
- const handleKeyDown = (e) => {
83
- // The expected keyboard shortcut for selecting a focused item is the Space key
84
- if (e?.key === ' ') handleChange()
85
- }
85
+ const handleChange = linkProps.handleHref({ href, onPress })
86
+ const handleKeyDown = (event) => {
87
+ // The expected keyboard shortcut for selecting a focused item is the Space key
88
+ if (event?.key === ' ') handleChange(event)
89
+ }
86
90
 
87
- return (
88
- <Pressable
89
- href={href}
90
- onPress={handleChange}
91
- onKeyDown={handleKeyDown}
92
- hrefAttrs={hrefAttrs}
93
- style={getOuterBorderStyle}
94
- {...a11y}
95
- >
96
- {(pressableState) => (
97
- <CardBase tokens={getCardTokens(pressableState)}>
98
- {typeof children === 'function' ? children(getCardState(pressableState)) : children}
99
- </CardBase>
100
- )}
101
- </Pressable>
102
- )
103
- }
91
+ return (
92
+ <Pressable
93
+ ref={ref}
94
+ href={href}
95
+ onPress={handleChange}
96
+ onKeyDown={handleKeyDown}
97
+ hrefAttrs={hrefAttrs}
98
+ style={getOuterBorderStyle}
99
+ {...a11y}
100
+ >
101
+ {(pressableState) => (
102
+ <CardBase tokens={getCardTokens(pressableState)}>
103
+ {typeof children === 'function' ? children(getCardState(pressableState)) : children}
104
+ </CardBase>
105
+ )}
106
+ </Pressable>
107
+ )
108
+ }
109
+ )
110
+ PressableCardBase.displayName = 'PressableCardBase'
104
111
 
105
112
  PressableCardBase.propTypes = {
106
113
  children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
@@ -1,6 +1,6 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { Pressable, StyleSheet, Text, View } from 'react-native'
3
+ import { Platform, Pressable, StyleSheet, Text, View } from 'react-native'
4
4
 
5
5
  import CheckboxInput from './CheckboxInput'
6
6
  // @todo move `LabelContent` outside of the `InputLabel` and fix
@@ -32,12 +32,16 @@ const selectInputStyles = (
32
32
  borderWidth: inputBorderWidth,
33
33
  borderRadius: inputBorderRadius,
34
34
  backgroundColor: isChecked ? iconBackgroundColor : inputBackgroundColor,
35
- outlineStyle: 'solid',
36
- outlineColor: inputOutlineColor,
37
- outlineWidth: inputOutlineWidth,
38
35
  height: inputHeight,
39
36
  width: inputWidth,
40
- ...applyShadowToken(inputShadow)
37
+ ...applyShadowToken(inputShadow),
38
+ ...Platform.select({
39
+ web: {
40
+ outlineStyle: 'solid',
41
+ outlineColor: inputOutlineColor,
42
+ outlineWidth: inputOutlineWidth
43
+ }
44
+ })
41
45
  })
42
46
  const selectLabelStyles = ({
43
47
  labelColor,
@@ -103,115 +107,121 @@ const selectFeedbackTokens = ({ feedbackMarginBottom, feedbackMarginTop, feedbac
103
107
  * or the internal state in case of uncontrolled checkbox.
104
108
  *
105
109
  */
106
- const Checkbox = ({
107
- checked,
108
- defaultChecked,
109
- error = false,
110
- feedback,
111
- id,
112
- inactive,
113
- label,
114
- name,
115
- onChange,
116
- tokens,
117
- value,
118
- variant,
119
- ...rest
120
- }) => {
121
- const { currentValue: isChecked, setValue: setIsChecked, isControlled } = useInputValue(
110
+ const Checkbox = forwardRef(
111
+ (
122
112
  {
123
- value: checked,
124
- initialValue: defaultChecked,
125
- onChange
113
+ checked,
114
+ defaultChecked,
115
+ error = false,
116
+ feedback,
117
+ id,
118
+ inactive,
119
+ label,
120
+ name,
121
+ onChange,
122
+ tokens,
123
+ value,
124
+ variant,
125
+ ...rest
126
126
  },
127
- 'useCheckboxValue'
128
- )
129
- const getTokens = useThemeTokensCallback('Checkbox', tokens, {
130
- checked: isChecked,
131
- inactive,
132
- error,
133
- ...variant
134
- })
135
- const defaultTokens = getTokens()
136
- const { feedbackMarginBottom, feedbackMarginTop, feedbackPosition } = selectFeedbackTokens(
137
- defaultTokens
138
- )
139
- const styles = StyleSheet.create({
140
- feedbackContainer: { marginTop: feedbackMarginTop, marginBottom: feedbackMarginBottom }
141
- })
142
- const handleChange = () => {
143
- if (!inactive) {
144
- setIsChecked(!isChecked)
127
+ ref
128
+ ) => {
129
+ const { currentValue: isChecked, setValue: setIsChecked, isControlled } = useInputValue(
130
+ {
131
+ value: checked,
132
+ initialValue: defaultChecked,
133
+ onChange
134
+ },
135
+ 'useCheckboxValue'
136
+ )
137
+ const getTokens = useThemeTokensCallback('Checkbox', tokens, {
138
+ checked: isChecked,
139
+ inactive,
140
+ error,
141
+ ...variant
142
+ })
143
+ const defaultTokens = getTokens()
144
+ const { feedbackMarginBottom, feedbackMarginTop, feedbackPosition } = selectFeedbackTokens(
145
+ defaultTokens
146
+ )
147
+ const styles = StyleSheet.create({
148
+ feedbackContainer: { marginTop: feedbackMarginTop, marginBottom: feedbackMarginBottom }
149
+ })
150
+ const handleChange = (event) => {
151
+ if (!inactive) {
152
+ setIsChecked(!isChecked, event)
153
+ }
145
154
  }
146
- }
147
- const handleKeyDown = (e) => {
148
- // The expected keyboard shortcut for activating a checkbox is the Space key
149
- if (e?.key === ' ') handleChange()
150
- }
151
- const accessibilityProps = a11yProps.select(rest)
152
- const uniqueId = useUniqueId('checkbox')
153
- const inputId = id ?? uniqueId
155
+ const handleKeyDown = (event) => {
156
+ // The expected keyboard shortcut for activating a checkbox is the Space key
157
+ if (event?.key === ' ') handleChange(event)
158
+ }
159
+ const accessibilityProps = a11yProps.select(rest)
160
+ const uniqueId = useUniqueId('checkbox')
161
+ const inputId = id ?? uniqueId
154
162
 
155
- return (
156
- <View style={staticStyles.wrapper}>
157
- <StackView direction={feedbackPosition === 'top' ? 'column-reverse' : 'column'} space={0}>
158
- <Pressable
159
- disabled={inactive}
160
- onKeyDown={handleKeyDown}
161
- onPress={handleChange}
162
- accessibilityRole="checkbox"
163
- accessibilityState={{ checked: isChecked, disabled: inactive }}
164
- {...accessibilityProps}
165
- >
166
- {({ focused: focus, hovered: hover, pressed }) => {
167
- const { icon: IconComponent, ...stateTokens } = getTokens({ focus, hover, pressed })
168
- const iconTokens = selectIconTokens(stateTokens)
163
+ return (
164
+ <View style={staticStyles.wrapper} ref={ref}>
165
+ <StackView direction={feedbackPosition === 'top' ? 'column-reverse' : 'column'} space={0}>
166
+ <Pressable
167
+ disabled={inactive}
168
+ onKeyDown={handleKeyDown}
169
+ onPress={handleChange}
170
+ accessibilityRole="checkbox"
171
+ accessibilityState={{ checked: isChecked, disabled: inactive }}
172
+ {...accessibilityProps}
173
+ >
174
+ {({ focused: focus, hovered: hover, pressed }) => {
175
+ const { icon: IconComponent, ...stateTokens } = getTokens({ focus, hover, pressed })
176
+ const iconTokens = selectIconTokens(stateTokens)
169
177
 
170
- return (
171
- <View style={staticStyles.container}>
172
- <View
173
- style={StyleSheet.flatten([
174
- staticStyles.defaultInputStyles,
175
- selectInputStyles(stateTokens, isChecked)
176
- ])}
177
- testID="Checkbox-Input"
178
- >
179
- {/* Add a real input on Web, skip on native platforms */}
180
- <CheckboxInput
181
- checked={isChecked}
182
- defaultChecked={defaultChecked}
183
- disabled={inactive}
184
- id={inputId}
185
- isControlled={isControlled}
186
- name={name}
187
- value={value}
188
- />
189
- {isChecked && IconComponent && (
190
- <IconComponent {...iconTokens} testID="Checkbox-Icon" />
178
+ return (
179
+ <View style={staticStyles.container}>
180
+ <View
181
+ style={StyleSheet.flatten([
182
+ staticStyles.defaultInputStyles,
183
+ selectInputStyles(stateTokens, isChecked)
184
+ ])}
185
+ testID="Checkbox-Input"
186
+ >
187
+ {/* Add a real input on Web, skip on native platforms */}
188
+ <CheckboxInput
189
+ checked={isChecked}
190
+ defaultChecked={defaultChecked}
191
+ disabled={inactive}
192
+ id={inputId}
193
+ isControlled={isControlled}
194
+ name={name}
195
+ value={value}
196
+ />
197
+ {isChecked && IconComponent && (
198
+ <IconComponent {...iconTokens} testID="Checkbox-Icon" />
199
+ )}
200
+ </View>
201
+ {Boolean(label) && (
202
+ <Text style={selectLabelStyles(stateTokens)}>
203
+ <CheckboxLabel forId={inputId}>{label}</CheckboxLabel>
204
+ </Text>
191
205
  )}
192
206
  </View>
193
- {Boolean(label) && (
194
- <Text style={selectLabelStyles(stateTokens)}>
195
- <CheckboxLabel forId={inputId}>{label}</CheckboxLabel>
196
- </Text>
197
- )}
198
- </View>
199
- )
200
- }}
201
- </Pressable>
202
- {Boolean(feedback) && (
203
- <View style={styles.feedbackContainer}>
204
- <Feedback
205
- title={feedback}
206
- variant={{ icon: error === true }}
207
- validation={error === true ? 'error' : undefined}
208
- />
209
- </View>
210
- )}
211
- </StackView>
212
- </View>
213
- )
214
- }
207
+ )
208
+ }}
209
+ </Pressable>
210
+ {Boolean(feedback) && (
211
+ <View style={styles.feedbackContainer}>
212
+ <Feedback
213
+ title={feedback}
214
+ variant={{ icon: error === true }}
215
+ validation={error === true ? 'error' : undefined}
216
+ />
217
+ </View>
218
+ )}
219
+ </StackView>
220
+ </View>
221
+ )
222
+ }
223
+ )
224
+ Checkbox.displayName = 'Checkbox'
215
225
 
216
226
  Checkbox.propTypes = {
217
227
  ...a11yProps.propTypes,
@@ -1,5 +1,6 @@
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
 
4
5
  import { useViewport } from '../ViewportProvider'
5
6
  import { useThemeTokens } from '../ThemeProvider'
@@ -55,71 +56,79 @@ import Fieldset from '../Fieldset'
55
56
  * />
56
57
  * ```
57
58
  */
58
- const CheckboxGroup = ({
59
- tokens,
60
- radioTokens,
61
- variant,
62
- items = [],
63
- legend,
64
- tooltip,
65
- hint,
66
- validation,
67
- feedback,
68
- initialCheckedIds,
69
- checkedIds,
70
- onChange,
71
- readOnly,
72
- name: inputGroupName,
73
- inactive
74
- }) => {
75
- const viewport = useViewport()
59
+ const CheckboxGroup = forwardRef(
60
+ (
61
+ {
62
+ tokens,
63
+ radioTokens,
64
+ variant,
65
+ items = [],
66
+ legend,
67
+ tooltip,
68
+ hint,
69
+ validation,
70
+ feedback,
71
+ initialCheckedIds,
72
+ checkedIds,
73
+ onChange,
74
+ readOnly,
75
+ name: inputGroupName,
76
+ inactive
77
+ },
78
+ ref
79
+ ) => {
80
+ const viewport = useViewport()
76
81
 
77
- const { space, fieldSpace } = useThemeTokens('CheckboxGroup', tokens, variant, {
78
- viewport
79
- })
82
+ const { space, fieldSpace } = useThemeTokens('CheckboxGroup', tokens, variant, {
83
+ viewport
84
+ })
85
+
86
+ const { currentValues, toggleOneValue } = useMultipleInputValues({
87
+ values: checkedIds,
88
+ initialValues: initialCheckedIds,
89
+ onChange,
90
+ readOnly: readOnly || inactive
91
+ })
92
+ const checkboxes = items.map(({ label, id, onChange: itemOnChange, ref: itemRef }, index) => {
93
+ const checkboxId = id || `Checkbox[${index}]`
94
+ const handleChange = (newCheckedState, event) => {
95
+ if (typeof itemOnChange === 'function') itemOnChange(newCheckedState, event)
96
+ toggleOneValue(checkboxId, event)
97
+ }
98
+ return (
99
+ <Checkbox
100
+ ref={itemRef}
101
+ key={checkboxId}
102
+ id={checkboxId}
103
+ checked={currentValues.includes(checkboxId)}
104
+ onChange={handleChange}
105
+ inactive={inactive}
106
+ label={label}
107
+ name={inputGroupName}
108
+ tokens={radioTokens}
109
+ variant={variant}
110
+ />
111
+ )
112
+ })
80
113
 
81
- const { currentValues, toggleOneValue } = useMultipleInputValues({
82
- values: checkedIds,
83
- initialValues: initialCheckedIds,
84
- onChange,
85
- readOnly: readOnly || inactive
86
- })
87
- const checkboxes = items.map(({ label, id, onChange: itemOnChange }, index) => {
88
- const checkboxId = id || `Checkbox[${index}]`
89
- const handleChange = (...args) => {
90
- if (typeof itemOnChange === 'function') itemOnChange(...args)
91
- toggleOneValue(checkboxId)
92
- }
93
114
  return (
94
- <Checkbox
95
- key={checkboxId}
96
- id={checkboxId}
97
- checked={currentValues.includes(checkboxId)}
98
- onChange={handleChange}
99
- inactive={inactive}
100
- label={label}
115
+ <Fieldset
116
+ ref={ref}
101
117
  name={inputGroupName}
102
- tokens={radioTokens}
103
- variant={variant}
104
- />
118
+ legend={legend}
119
+ tooltip={tooltip}
120
+ hint={hint}
121
+ space={fieldSpace}
122
+ feedback={feedback}
123
+ inactive={inactive}
124
+ validation={validation}
125
+ >
126
+ {getStackedContent(checkboxes, { space, direction: 'column' })}
127
+ </Fieldset>
105
128
  )
106
- })
107
-
108
- return (
109
- <Fieldset
110
- name={inputGroupName}
111
- legend={legend}
112
- tooltip={tooltip}
113
- hint={hint}
114
- space={fieldSpace}
115
- feedback={feedback}
116
- inactive={inactive}
117
- status={validation}
118
- >
119
- {getStackedContent(checkboxes, { space, direction: 'column' })}
120
- </Fieldset>
121
- )
122
- }
129
+ }
130
+ )
131
+ CheckboxGroup.displayName = 'CheckboxGroup'
123
132
 
124
133
  CheckboxGroup.propTypes = {
125
134
  /**
@@ -141,7 +150,8 @@ CheckboxGroup.propTypes = {
141
150
  PropTypes.exact({
142
151
  label: PropTypes.string,
143
152
  id: PropTypes.string,
144
- onChange: PropTypes.func
153
+ onChange: PropTypes.func,
154
+ ref: ABBPropTypes.ref()
145
155
  })
146
156
  ),
147
157
  /**
@@ -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 { View, StyleSheet, Platform } from 'react-native'
4
4
  import { useThemeTokens } from '../ThemeProvider'
@@ -45,7 +45,7 @@ import { getTokensPropType, variantProp, spacingProps } from '../utils'
45
45
  *
46
46
  * For accessibility purposes a divider component will be described with ARIA attributes, i.e. `role="separator"` and `aria-orientation="vertical/horizontal"`.
47
47
  */
48
- const Divider = ({ variant, vertical = false, space, tokens, testID }) => {
48
+ const Divider = forwardRef(({ variant, vertical = false, space, tokens, testID }, ref) => {
49
49
  const { color, width } = useThemeTokens('Divider', tokens, variant)
50
50
 
51
51
  const borderStyles = vertical
@@ -68,7 +68,9 @@ const Divider = ({ variant, vertical = false, space, tokens, testID }) => {
68
68
  : // There are no such equivalent attributes for native
69
69
  {}
70
70
 
71
- const divider = <View style={[styles.divider, borderStyles]} testID={testID} {...a11y} />
71
+ const divider = (
72
+ <View ref={ref} style={[styles.divider, borderStyles]} testID={testID} {...a11y} />
73
+ )
72
74
  if (!space) return divider
73
75
  const spacerProps = { space, direction: vertical ? 'row' : 'column' }
74
76
  return (
@@ -78,7 +80,8 @@ const Divider = ({ variant, vertical = false, space, tokens, testID }) => {
78
80
  <Spacer {...spacerProps} testID={testID ? `${testID}-Spacer-after` : undefined} />
79
81
  </>
80
82
  )
81
- }
83
+ })
84
+ Divider.displayName = 'Divider'
82
85
 
83
86
  Divider.propTypes = {
84
87
  tokens: getTokensPropType('Divider'),
@@ -1,10 +1,11 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import ExpandCollapse from './ExpandCollapse'
3
3
 
4
4
  /**
5
5
  * 'Accordion' is a shorthand for an ExpandCollapse where only one item may be open at a time
6
6
  */
7
- const Accordion = (props) => <ExpandCollapse {...props} maxOpen={1} />
7
+ const Accordion = forwardRef((props, ref) => <ExpandCollapse ref={ref} {...props} maxOpen={1} />)
8
+ Accordion.displayName = 'Accordion'
8
9
  Accordion.propTypes = ExpandCollapse.propTypes
9
10
 
10
11
  export default Accordion