@telus-uds/components-base 0.0.2-prerelease.1 → 0.0.2-prerelease.5

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 (161) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/__fixtures__/testTheme.js +264 -84
  3. package/__tests__/Box/Box.test.jsx +81 -58
  4. package/__tests__/Card/Card.test.jsx +63 -0
  5. package/__tests__/Divider/Divider.test.jsx +26 -5
  6. package/__tests__/Feedback/Feedback.test.jsx +42 -0
  7. package/__tests__/FlexGrid/Col.test.jsx +5 -0
  8. package/__tests__/Pagination/Pagination.test.jsx +160 -0
  9. package/__tests__/Spacer/Spacer.test.jsx +63 -0
  10. package/__tests__/StackView/StackView.test.jsx +242 -0
  11. package/__tests__/StackView/StackWrap.test.jsx +47 -0
  12. package/__tests__/StackView/getStackedContent.test.jsx +295 -0
  13. package/__tests__/TextInput/TextInput.test.jsx +146 -0
  14. package/__tests__/ThemeProvider/useThemeTokens.test.jsx +5 -3
  15. package/__tests__/utils/spacing.test.jsx +273 -0
  16. package/__tests__/utils/useUniqueId.test.js +31 -0
  17. package/babel.config.json +8 -0
  18. package/jest.config.js +7 -6
  19. package/lib/A11yInfoProvider/index.js +2 -2
  20. package/lib/A11yText/index.js +1 -3
  21. package/lib/ActivityIndicator/Spinner.web.js +3 -5
  22. package/lib/Box/Box.js +117 -82
  23. package/lib/Button/Button.js +1 -3
  24. package/lib/Button/ButtonBase.js +9 -21
  25. package/lib/Button/ButtonGroup.js +14 -25
  26. package/lib/Button/ButtonLink.js +1 -3
  27. package/lib/Card/Card.js +103 -0
  28. package/lib/Card/index.js +2 -0
  29. package/lib/Divider/Divider.js +40 -4
  30. package/lib/ExpandCollapse/Accordion.js +1 -3
  31. package/lib/ExpandCollapse/Control.js +3 -5
  32. package/lib/ExpandCollapse/Panel.js +2 -4
  33. package/lib/Feedback/Feedback.js +110 -0
  34. package/lib/Feedback/index.js +2 -0
  35. package/lib/FlexGrid/Col/Col.js +3 -5
  36. package/lib/FlexGrid/FlexGrid.js +1 -3
  37. package/lib/FlexGrid/Row/Row.js +1 -3
  38. package/lib/FlexGrid/providers/GutterContext.js +1 -1
  39. package/lib/Icon/Icon.js +1 -1
  40. package/lib/InputLabel/InputLabel.js +86 -0
  41. package/lib/InputLabel/LabelContent.native.js +8 -0
  42. package/lib/InputLabel/LabelContent.web.js +17 -0
  43. package/lib/InputLabel/index.js +2 -0
  44. package/lib/Link/ChevronLink.js +1 -3
  45. package/lib/Link/Link.js +1 -3
  46. package/lib/Link/LinkBase.js +11 -7
  47. package/lib/Link/TextButton.js +1 -3
  48. package/lib/Pagination/PageButton.js +85 -0
  49. package/lib/Pagination/Pagination.js +118 -0
  50. package/lib/Pagination/SideButton.js +108 -0
  51. package/lib/Pagination/dictionary.js +18 -0
  52. package/lib/Pagination/index.js +2 -0
  53. package/lib/Pagination/useCopy.js +10 -0
  54. package/lib/Pagination/usePagination.js +70 -0
  55. package/lib/SideNav/Item.js +4 -6
  56. package/lib/SideNav/ItemsGroup.js +11 -11
  57. package/lib/SideNav/SideNav.js +2 -4
  58. package/lib/Spacer/Spacer.js +98 -0
  59. package/lib/Spacer/index.js +2 -0
  60. package/lib/StackView/StackView.js +105 -0
  61. package/lib/StackView/StackWrap.js +32 -0
  62. package/lib/StackView/StackWrap.native.js +3 -0
  63. package/lib/StackView/StackWrapBox.js +85 -0
  64. package/lib/StackView/StackWrapGap.js +45 -0
  65. package/lib/StackView/common.js +30 -0
  66. package/lib/StackView/getStackedContent.js +111 -0
  67. package/lib/StackView/index.js +5 -0
  68. package/lib/TextInput/TextInput.js +337 -0
  69. package/lib/TextInput/index.js +2 -0
  70. package/lib/ThemeProvider/ThemeProvider.js +2 -2
  71. package/lib/ThemeProvider/useThemeTokens.js +34 -6
  72. package/lib/ThemeProvider/utils/theme-tokens.js +37 -9
  73. package/lib/ToggleSwitch/ToggleSwitch.js +17 -47
  74. package/lib/Typography/Typography.js +1 -7
  75. package/lib/ViewportProvider/index.js +1 -1
  76. package/lib/index.js +8 -1
  77. package/lib/utils/index.js +2 -1
  78. package/lib/utils/input.js +3 -1
  79. package/lib/utils/propTypes.js +103 -8
  80. package/lib/utils/spacing/index.js +2 -0
  81. package/lib/utils/spacing/useSpacingScale.js +102 -0
  82. package/lib/utils/spacing/utils.js +32 -0
  83. package/lib/utils/useUniqueId.js +12 -0
  84. package/package.json +6 -9
  85. package/release-context.json +4 -4
  86. package/src/Box/Box.jsx +117 -80
  87. package/src/Button/ButtonBase.jsx +8 -21
  88. package/src/Button/ButtonGroup.jsx +13 -17
  89. package/src/Card/Card.jsx +101 -0
  90. package/src/Card/index.js +3 -0
  91. package/src/Divider/Divider.jsx +38 -3
  92. package/src/ExpandCollapse/Control.jsx +2 -3
  93. package/src/Feedback/Feedback.jsx +99 -0
  94. package/src/Feedback/index.js +3 -0
  95. package/src/FlexGrid/Col/Col.jsx +4 -2
  96. package/src/Icon/Icon.jsx +2 -1
  97. package/src/InputLabel/InputLabel.jsx +99 -0
  98. package/src/InputLabel/LabelContent.native.jsx +6 -0
  99. package/src/InputLabel/LabelContent.web.jsx +13 -0
  100. package/src/InputLabel/index.js +3 -0
  101. package/src/Link/LinkBase.jsx +9 -3
  102. package/src/Pagination/PageButton.jsx +80 -0
  103. package/src/Pagination/Pagination.jsx +135 -0
  104. package/src/Pagination/SideButton.jsx +93 -0
  105. package/src/Pagination/dictionary.js +18 -0
  106. package/src/Pagination/index.js +3 -0
  107. package/src/Pagination/useCopy.js +7 -0
  108. package/src/Pagination/usePagination.js +69 -0
  109. package/src/SideNav/Item.jsx +3 -3
  110. package/src/SideNav/ItemsGroup.jsx +11 -13
  111. package/src/Spacer/Spacer.jsx +91 -0
  112. package/src/Spacer/index.js +3 -0
  113. package/src/StackView/StackView.jsx +103 -0
  114. package/src/StackView/StackWrap.jsx +33 -0
  115. package/src/StackView/StackWrap.native.jsx +4 -0
  116. package/src/StackView/StackWrapBox.jsx +82 -0
  117. package/src/StackView/StackWrapGap.jsx +39 -0
  118. package/src/StackView/common.jsx +28 -0
  119. package/src/StackView/getStackedContent.jsx +106 -0
  120. package/src/StackView/index.js +6 -0
  121. package/src/TextInput/TextInput.jsx +325 -0
  122. package/src/TextInput/index.js +3 -0
  123. package/src/ThemeProvider/useThemeTokens.js +34 -7
  124. package/src/ThemeProvider/utils/theme-tokens.js +37 -8
  125. package/src/ToggleSwitch/ToggleSwitch.jsx +23 -43
  126. package/src/Typography/Typography.jsx +0 -4
  127. package/src/index.js +8 -1
  128. package/src/utils/index.js +1 -0
  129. package/src/utils/input.js +2 -1
  130. package/src/utils/propTypes.js +105 -16
  131. package/src/utils/spacing/index.js +3 -0
  132. package/src/utils/spacing/useSpacingScale.js +93 -0
  133. package/src/utils/spacing/utils.js +28 -0
  134. package/src/utils/useUniqueId.js +14 -0
  135. package/stories/A11yText/A11yText.stories.jsx +11 -5
  136. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +11 -2
  137. package/stories/Box/Box.stories.jsx +46 -17
  138. package/stories/Button/Button.stories.jsx +17 -21
  139. package/stories/Button/ButtonGroup.stories.jsx +2 -1
  140. package/stories/Button/ButtonLink.stories.jsx +6 -4
  141. package/stories/Card/Card.stories.jsx +62 -0
  142. package/stories/Divider/Divider.stories.jsx +26 -2
  143. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +74 -79
  144. package/stories/Feedback/Feedback.stories.jsx +97 -0
  145. package/stories/FlexGrid/01 FlexGrid.stories.jsx +20 -7
  146. package/stories/Icon/Icon.stories.jsx +11 -3
  147. package/stories/InputLabel/InputLabel.stories.jsx +37 -0
  148. package/stories/Link/ChevronLink.stories.jsx +20 -4
  149. package/stories/Link/Link.stories.jsx +24 -3
  150. package/stories/Link/TextButton.stories.jsx +24 -3
  151. package/stories/Pagination/Pagination.stories.jsx +64 -0
  152. package/stories/SideNav/SideNav.stories.jsx +17 -2
  153. package/stories/Spacer/Spacer.stories.jsx +33 -0
  154. package/stories/StackView/StackView.stories.jsx +65 -0
  155. package/stories/StackView/StackWrap.stories.jsx +52 -0
  156. package/stories/TextInput/TextInput.stories.jsx +103 -0
  157. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +16 -3
  158. package/stories/Typography/Typography.stories.jsx +12 -3
  159. package/stories/platform-supports.web.jsx +1 -1
  160. package/stories/supports.jsx +113 -13
  161. package/babel.config.js +0 -3
@@ -1,5 +1,3 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import { Pressable, Text, View, StyleSheet, Platform } from 'react-native';
5
3
  import { useThemeTokensCallback } from '../ThemeProvider';
@@ -21,6 +19,7 @@ const getOuterBorderOffset = ({
21
19
  }) => outerBorderGap + outerBorderWidth;
22
20
 
23
21
  const selectOuterContainerStyles = ({
22
+ alignSelf,
24
23
  opacity,
25
24
  outerBorderColor,
26
25
  outerBorderWidth,
@@ -28,6 +27,7 @@ const selectOuterContainerStyles = ({
28
27
  outerBorderRadius = 0,
29
28
  outerBackgroundColor
30
29
  }) => ({
30
+ alignSelf,
31
31
  padding: outerBorderGap,
32
32
  borderWidth: outerBorderWidth,
33
33
  borderColor: outerBorderColor,
@@ -39,13 +39,7 @@ const selectOuterContainerStyles = ({
39
39
  const selectOuterWidthStyles = ({
40
40
  outerBorderGap,
41
41
  outerBorderWidth,
42
- width,
43
- // TODO: make margin the responsibility of a parent
44
- // https://github.com/telus/universal-design-system/issues/525
45
- marginTop = 0,
46
- marginBottom = 0,
47
- marginLeft = 0,
48
- marginRight = 0
42
+ width
49
43
  }) => {
50
44
  // The inner container's bounding box is the bounding box of the button overall
51
45
  // so this many device pixels will sit outside of the overall bounding box
@@ -54,22 +48,16 @@ const selectOuterWidthStyles = ({
54
48
  outerBorderWidth
55
49
  });
56
50
  const widthStyles = {
57
- marginTop: marginTop - outerBorderOffset,
58
- marginBottom: marginBottom - outerBorderOffset,
59
- marginLeft: marginLeft - outerBorderOffset,
60
- marginRight: marginRight - outerBorderOffset
51
+ margin: 0 - outerBorderOffset
61
52
  };
62
53
 
63
54
  if (!width) {
64
55
  return { ...widthStyles,
65
56
  // Wrap content, stopping a flex parent's default align-items: stretch stretching focus ring beyond content
66
57
  ...Platform.select({
58
+ // width: fit-content isn't supported on Firefox; can't cascade props like CSS `width: fit-content; width: --moz-fit-content;`
67
59
  web: {
68
- width: 'fit-content'
69
- },
70
- // No fit-content or inline-block in RN. TODO: we might need to provide a prop to allow flex-end or center
71
- native: {
72
- alignSelf: 'flex-start'
60
+ display: 'inline-flex'
73
61
  }
74
62
  })
75
63
  };
@@ -171,7 +159,7 @@ const ButtonBase = ({
171
159
  selected = false,
172
160
  ...rest
173
161
  }) => {
174
- const getTokens = useThemeTokensCallback('Button');
162
+ const getTokens = useThemeTokensCallback('Button', tokens, variant);
175
163
 
176
164
  const getButtonState = ({
177
165
  pressed,
@@ -185,7 +173,7 @@ const ButtonBase = ({
185
173
  selected
186
174
  });
187
175
 
188
- const getTokensByPressableState = pressableState => getTokens(tokens, variant, getButtonState(pressableState));
176
+ const getTokensByPressableState = pressableState => getTokens(getButtonState(pressableState));
189
177
 
190
178
  const a11y = a11yProps.select(rest);
191
179
 
@@ -198,7 +186,7 @@ const ButtonBase = ({
198
186
  href,
199
187
  onPress
200
188
  });
201
- return /*#__PURE__*/React.createElement(Pressable, _extends({
189
+ return /*#__PURE__*/React.createElement(Pressable, Object.assign({
202
190
  onPress: handlePress,
203
191
  style: getPressableStyle,
204
192
  disabled: inactive,
@@ -1,26 +1,13 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import PropTypes from 'prop-types';
5
- import { View, Platform } from 'react-native';
3
+ import { Platform } from 'react-native';
6
4
  import ButtonBase from './ButtonBase';
5
+ import { StackWrap } from '../StackView';
7
6
  import { useViewport } from '../ViewportProvider';
8
7
  import { useThemeTokens } from '../ThemeProvider';
9
- import { a11yProps, pressProps, variantProp, getTokensPropType } from '../utils/propTypes';
8
+ import { a11yProps, pressProps, variantProp, getTokensPropType, selectTokens } from '../utils/propTypes';
10
9
  import { useMultipleInputValues } from '../utils/input';
11
10
 
12
- const selectContainerStyles = ({
13
- direction
14
- }) => ({
15
- flexDirection: direction
16
- });
17
-
18
- const selectItemTokens = ({
19
- gap
20
- }, index) => ({
21
- marginLeft: index && gap
22
- });
23
-
24
11
  const ButtonGroup = ({
25
12
  variant,
26
13
  buttonVariant = {},
@@ -43,7 +30,11 @@ const ButtonGroup = ({
43
30
  const themeTokens = useThemeTokens('ButtonGroup', tokens, variant, {
44
31
  viewport
45
32
  });
46
- const containerStyles = selectContainerStyles(themeTokens);
33
+ const stackTokens = selectTokens('StackView', themeTokens);
34
+ const {
35
+ direction,
36
+ space
37
+ } = themeTokens;
47
38
  const {
48
39
  currentValues,
49
40
  toggleOneValue
@@ -59,14 +50,15 @@ const ButtonGroup = ({
59
50
  ...rest
60
51
  });
61
52
  const itemA11yRole = a11y.accessibilityRole === 'radioGroup' ? 'radio' : 'checkbox';
62
- return /*#__PURE__*/React.createElement(View, _extends({
63
- style: containerStyles
64
- }, a11y), items.map(({
53
+ return /*#__PURE__*/React.createElement(StackWrap, Object.assign({}, a11y, {
54
+ space: space,
55
+ direction: direction,
56
+ tokens: stackTokens
57
+ }), items.map(({
65
58
  label,
66
59
  id = label,
67
60
  accessibilityLabel
68
61
  }, index) => {
69
- const itemTokens = selectItemTokens(themeTokens, index);
70
62
  const isSelected = currentValues.includes(id); // Allow handlers to be passed down for blur, hover, focus, pressIn, etc
71
63
 
72
64
  const pressHandlers = Object.fromEntries(Object.entries(pressProps.select(rest)).map(([key, handler]) => ({
@@ -102,10 +94,8 @@ const ButtonGroup = ({
102
94
  })
103
95
  }; // Ensure button is direct child of group as MacOS voiceover only applies "X of Y" to
104
96
  // "radio" if it's a direct child of "radiogroup", even if aria-posinset etc exists
105
- // See also: TODO: make margin the responsibility of a parent
106
- // https://github.com/telus/universal-design-system/issues/525
107
97
 
108
- return /*#__PURE__*/React.createElement(ButtonBase, _extends({
98
+ return /*#__PURE__*/React.createElement(ButtonBase, Object.assign({
109
99
  key: id
110
100
  }, pressHandlers, {
111
101
  onPress: handlePress,
@@ -113,7 +103,6 @@ const ButtonGroup = ({
113
103
  component: 'ButtonGroup',
114
104
  ...buttonVariant
115
105
  },
116
- tokens: itemTokens,
117
106
  selected: isSelected,
118
107
  inactive: inactive
119
108
  }, itemA11y), label);
@@ -1,5 +1,3 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import ButtonBase from './ButtonBase';
5
3
  import buttonPropTypes from './propTypes';
@@ -17,7 +15,7 @@ const ButtonLink = ({
17
15
  hrefAttrs,
18
16
  rest
19
17
  } = hrefAttrsProp.bundle(props);
20
- return /*#__PURE__*/React.createElement(ButtonBase, _extends({
18
+ return /*#__PURE__*/React.createElement(ButtonBase, Object.assign({
21
19
  accessibilityRole: accessibilityRole,
22
20
  hrefAttrs: hrefAttrs
23
21
  }, rest));
@@ -0,0 +1,103 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { View } from 'react-native';
4
+ import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
5
+ import { getTokensPropType, variantProp } from '../utils';
6
+ import { useViewport } from '../ViewportProvider';
7
+ import { a11yProps } from '../utils/propTypes'; // Ensure explicit selection of tokens
8
+
9
+ const selectStyles = ({
10
+ backgroundColor,
11
+ borderColor,
12
+ borderRadius,
13
+ borderWidth,
14
+ paddingBottom,
15
+ paddingLeft,
16
+ paddingRight,
17
+ paddingTop,
18
+ shadow
19
+ }) => ({
20
+ backgroundColor,
21
+ borderColor,
22
+ borderRadius,
23
+ borderWidth,
24
+ paddingBottom,
25
+ paddingLeft,
26
+ paddingRight,
27
+ paddingTop,
28
+ ...applyShadowToken(shadow)
29
+ });
30
+ /**
31
+ * A basic card component, unstyled by default.
32
+ *
33
+ * ## Component API
34
+ *
35
+ * ### Background
36
+ *
37
+ * In order to control the background of a card, the following tokens are currently
38
+ * supported:
39
+ *
40
+ * - `backgroundColor`
41
+ *
42
+ * ### Border
43
+ *
44
+ * The following border tokens can be used:
45
+ *
46
+ * - `borderColor`
47
+ * - `borderRadius`
48
+ * - `borderWidth`
49
+ *
50
+ * ### Padding
51
+ *
52
+ * Please use the following tokens to control the padding:
53
+ *
54
+ * - `paddingBottom`
55
+ * - `paddingLeft`
56
+ * - `paddingRight`
57
+ * - `paddingTop`
58
+ *
59
+ * Note that various viewport sizes are supported as well.
60
+ *
61
+ * ### Shadow
62
+ *
63
+ * Feel free to use the following properties within the `shadow` token:
64
+ *
65
+ * - `inset`: boolean
66
+ * - `color`: string
67
+ * - `offsetX`: number
68
+ * - `offsetY`: number
69
+ * - `blur`: number
70
+ * - `spread`: number
71
+ *
72
+ * ## Accessibility
73
+ *
74
+ * Card supports all the common a11y props. Please remember that by marking a card as `accessible`
75
+ * you automatically make inaccessible its children, which may or may not be appropriate
76
+ * depending on what you are trying to achieve.
77
+ */
78
+
79
+
80
+ const Card = ({
81
+ children,
82
+ tokens,
83
+ variant,
84
+ ...rest
85
+ }) => {
86
+ const viewport = useViewport();
87
+ const themeTokens = useThemeTokens('Card', tokens, variant, {
88
+ viewport
89
+ });
90
+ const cardStyle = selectStyles(themeTokens);
91
+ const a11y = a11yProps.select(rest);
92
+ return /*#__PURE__*/React.createElement(View, Object.assign({
93
+ style: cardStyle
94
+ }, a11y), children);
95
+ };
96
+
97
+ Card.propTypes = {
98
+ children: PropTypes.node,
99
+ tokens: getTokensPropType('Card'),
100
+ variant: variantProp.propType,
101
+ ...a11yProps.types
102
+ };
103
+ export default Card;
@@ -0,0 +1,2 @@
1
+ import Card from './Card';
2
+ export default Card;
@@ -1,10 +1,14 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import PropTypes from 'prop-types';
5
3
  import { View, StyleSheet, Platform } from 'react-native';
6
4
  import { useThemeTokens } from '../ThemeProvider';
7
- import { getTokensPropType, variantProp } from '../utils/propTypes';
5
+ import Spacer from '../Spacer';
6
+ import { getTokensPropType, variantProp, spacingProps } from '../utils';
7
+ /**
8
+ * @typedef {import('../utils/propTypes.js').SpacingIndex} SpacingIndex
9
+ * @typedef {import('../utils/propTypes.js').SpacingObject} SpacingObject
10
+ */
11
+
8
12
  /**
9
13
  * A basic divider component, horizontal by default. Color and thickness can be controlled by theme.
10
14
  * Divider is based on the flexbox model and uses `alignSelf: flex` to span its flex parent.
@@ -17,6 +21,26 @@ import { getTokensPropType, variantProp } from '../utils/propTypes';
17
21
  *
18
22
  * In a flexbox row, vertical dividers will automatically size to their parent height.
19
23
  *
24
+ * ## Space
25
+ *
26
+ * Use this to create **space either side of the divider**. For simple cases, pass a number referring to
27
+ * a position on the theme's spacing scale; for example, this will put a Spacer of the smallest supported
28
+ * size either side of the divider:
29
+ *
30
+ * ```jsx
31
+ * <Divider space={1} />
32
+ * ```
33
+ *
34
+ * `space` prop uses `useSpacingScale` and may accept a {@link SpacingObject} or a {@link SpacingIndex} number.
35
+ *
36
+ * To **reduce the length of a divider** as well as creating space between it and its neighbours, wrap it in
37
+ * a `Box` component. For example, this will have the second-smallest theme-supported spacing value between
38
+ * the dividing line and its neighbours, and will shorten the line at either end by the same amount:
39
+ *
40
+ * ```jsx
41
+ * <Box space={2}><Divider /></Box>
42
+ * ```
43
+ *
20
44
  * ## Accessibility
21
45
  *
22
46
  * For accessibility purposes a divider component will be described with ARIA attributes, i.e. `role="separator"` and `aria-orientation="vertical/horizontal"`.
@@ -25,6 +49,7 @@ import { getTokensPropType, variantProp } from '../utils/propTypes';
25
49
  const Divider = ({
26
50
  variant,
27
51
  vertical = false,
52
+ space,
28
53
  tokens,
29
54
  testID
30
55
  }) => {
@@ -45,14 +70,25 @@ const Divider = ({
45
70
  accessibilityRole: 'separator'
46
71
  } : // There are no such equivalent attributes for native
47
72
  {};
48
- return /*#__PURE__*/React.createElement(View, _extends({
73
+ const divider = /*#__PURE__*/React.createElement(View, Object.assign({
49
74
  style: [styles.divider, borderStyles],
50
75
  testID: testID
51
76
  }, a11y));
77
+ if (!space) return divider;
78
+ const spacerProps = {
79
+ space,
80
+ direction: vertical ? 'row' : 'column'
81
+ };
82
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Spacer, Object.assign({}, spacerProps, {
83
+ testID: testID ? `${testID}-Spacer-before` : undefined
84
+ })), divider, /*#__PURE__*/React.createElement(Spacer, Object.assign({}, spacerProps, {
85
+ testID: testID ? `${testID}-Spacer-after` : undefined
86
+ })));
52
87
  };
53
88
 
54
89
  Divider.propTypes = {
55
90
  tokens: getTokensPropType('Divider'),
91
+ space: spacingProps.types.spacingValue,
56
92
  variant: variantProp.propType,
57
93
 
58
94
  /**
@@ -1,12 +1,10 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import ExpandCollapse from './ExpandCollapse';
5
3
  /**
6
4
  * 'Accordion' is a shorthand for an ExpandCollapse where only one item may be open at a time
7
5
  */
8
6
 
9
- const Accordion = props => /*#__PURE__*/React.createElement(ExpandCollapse, _extends({}, props, {
7
+ const Accordion = props => /*#__PURE__*/React.createElement(ExpandCollapse, Object.assign({}, props, {
10
8
  maxOpen: 1
11
9
  }));
12
10
 
@@ -1,5 +1,3 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import { Pressable, View } from 'react-native';
5
3
  import PropTypes from 'prop-types';
@@ -60,7 +58,7 @@ const ExpandCollapseControl = ({
60
58
  variant,
61
59
  rest
62
60
  }) => {
63
- const getTokens = useThemeTokensCallback('ExpandCollapseControl');
61
+ const getTokens = useThemeTokensCallback('ExpandCollapseControl', tokens, variant);
64
62
  const a11y = a11yProps.select({ ...rest,
65
63
  accessibilityRole
66
64
  });
@@ -79,11 +77,11 @@ const ExpandCollapseControl = ({
79
77
  expanded: isExpanded
80
78
  });
81
79
 
82
- const getControlTokens = pressableState => getTokens(tokens, variant, getControlState(pressableState));
80
+ const getControlTokens = pressableState => getTokens(getControlState(pressableState));
83
81
 
84
82
  const getPressableStyle = pressableState => selectContainerStyles(getControlTokens(pressableState));
85
83
 
86
- return /*#__PURE__*/React.createElement(Pressable, _extends({}, a11y, {
84
+ return /*#__PURE__*/React.createElement(Pressable, Object.assign({}, a11y, {
87
85
  onPress: onPress,
88
86
  style: getPressableStyle
89
87
  }), pressableState => {
@@ -1,5 +1,3 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React, { useState } from 'react';
4
2
  import { Animated, Platform, StyleSheet, View } from 'react-native';
5
3
  import PropTypes from 'prop-types';
@@ -84,11 +82,11 @@ const ExpandCollapsePanel = ({
84
82
  const focusabilityProps = isExpanded ? {} : a11yProps.nonFocusableProps;
85
83
  return /*#__PURE__*/React.createElement(View, {
86
84
  style: selectGroupStyles(themeTokens)
87
- }, /*#__PURE__*/React.createElement(ExpandCollapseControl, _extends({}, a11y, {
85
+ }, /*#__PURE__*/React.createElement(ExpandCollapseControl, Object.assign({}, a11y, {
88
86
  isExpanded: isExpanded,
89
87
  tokens: controlTokens,
90
88
  onPress: handleControlPress
91
- }), control), /*#__PURE__*/React.createElement(View, _extends({
89
+ }), control), /*#__PURE__*/React.createElement(View, Object.assign({
92
90
  style: overflowContainerStyles
93
91
  }, focusabilityProps), /*#__PURE__*/React.createElement(Animated.View, {
94
92
  onLayout: onContainerLayout,
@@ -0,0 +1,110 @@
1
+ import React from 'react';
2
+ import { Text, View, StyleSheet } from 'react-native';
3
+ import PropTypes from 'prop-types';
4
+ import { applyTextStyles, useThemeTokens } from '../ThemeProvider';
5
+ import { a11yProps, getTokensPropType, selectTokens, variantProp } from '../utils';
6
+
7
+ const selectStyles = tokens => selectTokens('Feedback', tokens);
8
+
9
+ const selectTitleTextStyles = ({
10
+ titleFontSize,
11
+ ...tokens
12
+ }) => applyTextStyles(selectTokens('Typography', { ...tokens,
13
+ fontSize: titleFontSize
14
+ }));
15
+
16
+ const selectContentTextStyles = ({
17
+ contentFontSize,
18
+ ...tokens
19
+ }) => applyTextStyles(selectTokens('Typography', { ...tokens,
20
+ fontSize: contentFontSize
21
+ }));
22
+
23
+ const selectIconTokens = ({
24
+ iconSize,
25
+ iconColor
26
+ }) => ({
27
+ size: iconSize,
28
+ color: iconColor
29
+ });
30
+
31
+ const selectIconContainerStyles = ({
32
+ iconGap
33
+ }) => ({
34
+ paddingRight: iconGap
35
+ });
36
+ /**
37
+ * A feedback box commonly used with form fields.
38
+ *
39
+ * ### Standalone usage
40
+ * While its primary use is to facilitate feedback states for other form components such as `TextInput`,
41
+ * you may use it standalone.
42
+ *
43
+ * ### Complex content
44
+ * You may pass any React tree as the children of this component, bear in mind that a render function
45
+ * is better suited for styling children based on Feedback's variant.
46
+ *
47
+ * ### Using a render function
48
+ * When a function is passed for rendering content, it will receive the feedback text styles and
49
+ * variant as arguments.
50
+ *
51
+ * ### Accessibility
52
+ * All accessibility props set on this component will be applied to the outer container.
53
+ */
54
+
55
+
56
+ const Feedback = ({
57
+ title,
58
+ children,
59
+ tokens,
60
+ variant,
61
+ ...rest
62
+ }) => {
63
+ const themeTokens = useThemeTokens('Feedback', tokens, variant);
64
+ const {
65
+ icon: IconComponent
66
+ } = themeTokens;
67
+ const titleTextStyles = selectTitleTextStyles(themeTokens);
68
+ const contentTextStyles = selectContentTextStyles(themeTokens);
69
+ const content = typeof children === 'string' ? /*#__PURE__*/React.createElement(Text, {
70
+ style: contentTextStyles
71
+ }, children) : children;
72
+ const accessibilityProps = a11yProps.select(rest); // TODO: use Stack to separate the title from content (space 2)
73
+
74
+ return /*#__PURE__*/React.createElement(View, Object.assign({
75
+ style: selectStyles(themeTokens)
76
+ }, accessibilityProps), title !== undefined && /*#__PURE__*/React.createElement(View, {
77
+ style: staticStyles.title
78
+ }, IconComponent && /*#__PURE__*/React.createElement(View, {
79
+ style: selectIconContainerStyles(themeTokens)
80
+ }, /*#__PURE__*/React.createElement(IconComponent, {
81
+ tokens: selectIconTokens(themeTokens)
82
+ })), /*#__PURE__*/React.createElement(Text, {
83
+ style: titleTextStyles
84
+ }, title)), content && typeof content === 'function' ? content({
85
+ textStyles: contentTextStyles,
86
+ variant
87
+ }) : /*#__PURE__*/React.createElement(View, null, content));
88
+ };
89
+
90
+ Feedback.propTypes = {
91
+ /**
92
+ * Emphasized summary of the feedback. If an icon is set, it is rendered next to the title.
93
+ */
94
+ title: PropTypes.string,
95
+
96
+ /**
97
+ * Feedback content rendered below the title. A render function `({textStyles, variant}) => {}` is supported.
98
+ */
99
+ children: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.func]),
100
+ tokens: getTokensPropType('Feedback'),
101
+ variant: variantProp.propType
102
+ };
103
+ export default Feedback;
104
+ const staticStyles = StyleSheet.create({
105
+ title: {
106
+ display: 'flex',
107
+ flexDirection: 'row',
108
+ alignItems: 'center'
109
+ }
110
+ });
@@ -0,0 +1,2 @@
1
+ import Feedback from './Feedback';
2
+ export default Feedback;
@@ -1,5 +1,3 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React, { useContext } from 'react';
4
2
  import PropTypes from 'prop-types';
5
3
  import { Platform, StyleSheet, View } from 'react-native';
@@ -7,7 +5,7 @@ import { viewports } from '@telus-uds/system-constants';
7
5
  import GutterContext from '../providers/GutterContext';
8
6
  import { useViewport } from '../../ViewportProvider';
9
7
  import applyInheritance from '../helpers';
10
- import { responsivePropTypeFactory } from '../../utils';
8
+ import { responsiveProps } from '../../utils';
11
9
 
12
10
  const Col = ({
13
11
  horizontalAlign,
@@ -151,7 +149,7 @@ const Col = ({
151
149
  lg: offsetsWithIheritance[3],
152
150
  xl: offsetsWithIheritance[4]
153
151
  };
154
- return /*#__PURE__*/React.createElement(View, _extends({}, viewProps, {
152
+ return /*#__PURE__*/React.createElement(View, Object.assign({}, viewProps, {
155
153
  style: [styles.col, gutterPadding, offsetStyles(offsets), sizeStyles(sizes), { ...hidingStyles
156
154
  }]
157
155
  }), children);
@@ -257,6 +255,6 @@ Col.propTypes = {
257
255
  *
258
256
  * Accepts a `PropType.string` following the [responsive prop](#/Layout?id=responsive) structure.
259
257
  */
260
- horizontalAlign: responsivePropTypeFactory(PropTypes.oneOf(['left', 'center', 'right']))
258
+ horizontalAlign: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(['left', 'center', 'right']))
261
259
  };
262
260
  export default Col;
@@ -1,5 +1,3 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import PropTypes from 'prop-types';
5
3
  import { View, StyleSheet } from 'react-native';
@@ -60,7 +58,7 @@ const FlexGrid = ({
60
58
 
61
59
  return /*#__PURE__*/React.createElement(GutterContext.Provider, {
62
60
  value: gutter
63
- }, /*#__PURE__*/React.createElement(View, _extends({}, rest, {
61
+ }, /*#__PURE__*/React.createElement(View, Object.assign({}, rest, {
64
62
  style: [styles.grid, {
65
63
  marginHorizontal,
66
64
  marginVertical,
@@ -1,5 +1,3 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import React from 'react';
4
2
  import PropTypes from 'prop-types';
5
3
  import { View, StyleSheet } from 'react-native';
@@ -107,7 +105,7 @@ const Row = ({
107
105
  flexDirection = reverseLevel[4] ? 'row-reverse' : 'row';
108
106
  }
109
107
 
110
- return /*#__PURE__*/React.createElement(View, _extends({}, rest, {
108
+ return /*#__PURE__*/React.createElement(View, Object.assign({}, rest, {
111
109
  style: [styles.row, {
112
110
  flexDirection,
113
111
  ...horizontalAlignStyles(horizontalAlign),
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
- const GutterContext = React.createContext(false);
2
+ const GutterContext = /*#__PURE__*/React.createContext(false);
3
3
  export default GutterContext;
package/lib/Icon/Icon.js CHANGED
@@ -23,7 +23,7 @@ const Icon = ({
23
23
  style: {
24
24
  // TODO: https://github.com/telus/universal-design-system/issues/487
25
25
  transition: 'transform 200ms',
26
- transform: [themeTokens.scale ? `scale(${themeTokens.scale})` : '', themeTokens.translateX ? `translateX(${themeTokens.translateX}px)` : ''].filter(exists => exists).join(' ')
26
+ transform: [themeTokens.scale ? `scale(${themeTokens.scale})` : '', themeTokens.translateX ? `translateX(${themeTokens.translateX}px)` : '', themeTokens.translateY ? `translateY(${themeTokens.translateY}px)` : ''].filter(exists => exists).join(' ')
27
27
  }
28
28
  }, iconContent) : iconContent;
29
29
  }; // Auto-generated SVG icon components wrap Icon and pass through these props: