@telus-uds/components-base 3.12.2 → 3.14.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 (63) hide show
  1. package/CHANGELOG.md +37 -2
  2. package/lib/cjs/BaseProvider/index.js +4 -1
  3. package/lib/cjs/Button/ButtonDropdown.js +105 -12
  4. package/lib/cjs/Card/Card.js +23 -4
  5. package/lib/cjs/Card/CardBase.js +170 -19
  6. package/lib/cjs/Card/PressableCardBase.js +19 -5
  7. package/lib/cjs/Card/backgroundImageStylesMap.js +197 -0
  8. package/lib/cjs/ExpandCollapse/ExpandCollapse.js +3 -1
  9. package/lib/cjs/ExpandCollapseMini/ExpandCollapseMini.js +1 -1
  10. package/lib/cjs/ExpandCollapseMini/ExpandCollapseMiniControl.js +30 -6
  11. package/lib/cjs/FlexGrid/FlexGrid.js +71 -6
  12. package/lib/cjs/Icon/Icon.js +3 -1
  13. package/lib/cjs/InputLabel/InputLabel.js +1 -1
  14. package/lib/cjs/InputSupports/InputSupports.js +1 -1
  15. package/lib/cjs/Notification/Notification.js +27 -8
  16. package/lib/cjs/Tabs/Tabs.js +34 -2
  17. package/lib/cjs/Tabs/TabsDropdown.js +252 -0
  18. package/lib/cjs/Tabs/TabsItem.js +4 -2
  19. package/lib/cjs/Tabs/dictionary.js +14 -0
  20. package/lib/cjs/ViewportProvider/ViewportProvider.js +9 -3
  21. package/lib/cjs/utils/props/inputSupportsProps.js +1 -1
  22. package/lib/esm/BaseProvider/index.js +4 -1
  23. package/lib/esm/Button/ButtonDropdown.js +107 -14
  24. package/lib/esm/Card/Card.js +21 -4
  25. package/lib/esm/Card/CardBase.js +169 -19
  26. package/lib/esm/Card/PressableCardBase.js +19 -5
  27. package/lib/esm/Card/backgroundImageStylesMap.js +190 -0
  28. package/lib/esm/ExpandCollapse/ExpandCollapse.js +4 -2
  29. package/lib/esm/ExpandCollapseMini/ExpandCollapseMini.js +2 -2
  30. package/lib/esm/ExpandCollapseMini/ExpandCollapseMiniControl.js +30 -6
  31. package/lib/esm/FlexGrid/FlexGrid.js +72 -7
  32. package/lib/esm/Icon/Icon.js +3 -1
  33. package/lib/esm/InputLabel/InputLabel.js +1 -1
  34. package/lib/esm/InputSupports/InputSupports.js +1 -1
  35. package/lib/esm/Notification/Notification.js +27 -8
  36. package/lib/esm/Tabs/Tabs.js +35 -3
  37. package/lib/esm/Tabs/TabsDropdown.js +245 -0
  38. package/lib/esm/Tabs/TabsItem.js +4 -2
  39. package/lib/esm/Tabs/dictionary.js +8 -0
  40. package/lib/esm/ViewportProvider/ViewportProvider.js +9 -3
  41. package/lib/esm/utils/props/inputSupportsProps.js +1 -1
  42. package/lib/package.json +2 -2
  43. package/package.json +2 -2
  44. package/src/BaseProvider/index.jsx +4 -2
  45. package/src/Button/ButtonDropdown.jsx +109 -16
  46. package/src/Card/Card.jsx +27 -3
  47. package/src/Card/CardBase.jsx +165 -19
  48. package/src/Card/PressableCardBase.jsx +31 -4
  49. package/src/Card/backgroundImageStylesMap.js +41 -0
  50. package/src/ExpandCollapse/ExpandCollapse.jsx +5 -2
  51. package/src/ExpandCollapseMini/ExpandCollapseMini.jsx +2 -2
  52. package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +39 -9
  53. package/src/FlexGrid/FlexGrid.jsx +80 -7
  54. package/src/Icon/Icon.jsx +3 -1
  55. package/src/InputLabel/InputLabel.jsx +1 -1
  56. package/src/InputSupports/InputSupports.jsx +1 -1
  57. package/src/Notification/Notification.jsx +58 -9
  58. package/src/Tabs/Tabs.jsx +36 -2
  59. package/src/Tabs/TabsDropdown.jsx +265 -0
  60. package/src/Tabs/TabsItem.jsx +4 -2
  61. package/src/Tabs/dictionary.js +8 -0
  62. package/src/ViewportProvider/ViewportProvider.jsx +8 -3
  63. package/src/utils/props/inputSupportsProps.js +1 -1
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+ var _Pressable = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Pressable"));
10
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
11
+ var _Text = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Text"));
12
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
13
+ var _ThemeProvider = require("../ThemeProvider");
14
+ var _utils = require("../utils");
15
+ var _ViewportProvider = require("../ViewportProvider");
16
+ var _Icon = _interopRequireDefault(require("../Icon"));
17
+ var _Listbox = _interopRequireDefault(require("../Listbox"));
18
+ var _dictionary = _interopRequireDefault(require("./dictionary"));
19
+ var _jsxRuntime = require("react/jsx-runtime");
20
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
21
+ const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
22
+ const selectButtonContentStyles = _ref => {
23
+ let {
24
+ backgroundColor,
25
+ borderColor,
26
+ borderWidth,
27
+ borderRadius,
28
+ paddingHorizontal,
29
+ paddingVertical,
30
+ marginHorizontal,
31
+ marginVertical
32
+ } = _ref;
33
+ return {
34
+ backgroundColor,
35
+ borderColor,
36
+ borderWidth,
37
+ borderRadius,
38
+ paddingHorizontal,
39
+ paddingVertical,
40
+ marginLeft: marginHorizontal,
41
+ marginRight: marginHorizontal,
42
+ marginTop: marginVertical,
43
+ marginBottom: marginVertical
44
+ };
45
+ };
46
+
47
+ /**
48
+ * TabsDropdown renders a dropdown version of tabs for mobile/tablet viewports.
49
+ * It shows the currently selected tab as a button that opens a dropdown menu
50
+ * containing all available tabs.
51
+ *
52
+ * This is rendered automatically by `Tabs` on mobile viewports and when variant
53
+ * is dropdown and isn't intended to be used directly.
54
+ */
55
+ const TabsDropdown = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
56
+ let {
57
+ itemTokens,
58
+ variant,
59
+ value,
60
+ onChange,
61
+ items = [],
62
+ LinkRouter,
63
+ linkRouterProps,
64
+ accessibilityRole = 'button',
65
+ copy = 'en',
66
+ dictionary: customDictionary = _dictionary.default,
67
+ ...rest
68
+ } = _ref2;
69
+ const {
70
+ themeOptions
71
+ } = (0, _ThemeProvider.useTheme)();
72
+ const viewport = (0, _ViewportProvider.useViewport)();
73
+ const [isOpen, setIsOpen] = _react.default.useState(false);
74
+ const getTokens = (0, _ThemeProvider.useThemeTokensCallback)('TabsItem', itemTokens, {
75
+ viewport,
76
+ ...variant
77
+ });
78
+ const selectedItem = items.find(item => {
79
+ const itemId = item.id ?? item.label;
80
+ return value === itemId;
81
+ }) || items[0];
82
+ const {
83
+ overlaidPosition,
84
+ sourceRef,
85
+ targetRef,
86
+ onTargetLayout,
87
+ isReady
88
+ } = (0, _utils.useOverlaidPosition)({
89
+ isShown: isOpen,
90
+ offsets: {
91
+ vertical: 4
92
+ },
93
+ align: {
94
+ top: 'bottom',
95
+ left: 'left'
96
+ }
97
+ });
98
+ const handleToggle = () => setIsOpen(prev => !prev);
99
+ const handleClose = () => setIsOpen(false);
100
+ const handleItemSelect = (item, event) => {
101
+ const itemId = item.id ?? item.label;
102
+ setIsOpen(false);
103
+ if (onChange) onChange(itemId, event);
104
+ if (item.onPress) item.onPress(event);
105
+ };
106
+ const listboxItems = items.map(item => ({
107
+ ...item,
108
+ onPress: event => handleItemSelect(item, event)
109
+ }));
110
+ const isSelected = Boolean(selectedItem && value);
111
+ const getCopy = (0, _utils.useCopy)({
112
+ dictionary: customDictionary,
113
+ copy
114
+ });
115
+ const selectedProps = selectProps({
116
+ accessibilityRole,
117
+ ...rest
118
+ });
119
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
120
+ ref: ref,
121
+ style: styles.container,
122
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Pressable.default, {
123
+ ref: sourceRef,
124
+ onPress: handleToggle,
125
+ ...selectedProps,
126
+ style: styles.pressable,
127
+ children: pressableState => {
128
+ // Use resolvePressableTokens like TabBarItem does for proper state handling
129
+ const resolvedTokens = (0, _utils.resolvePressableTokens)(getTokens, pressableState, {
130
+ viewport,
131
+ expanded: isOpen,
132
+ selected: isSelected
133
+ });
134
+ const textStyles = (0, _ThemeProvider.applyTextStyles)({
135
+ ...(0, _utils.selectTokens)('Typography', resolvedTokens),
136
+ themeOptions
137
+ });
138
+
139
+ // Get dropdown icons from resolved tokens
140
+ const dropdownIcon = isOpen ? resolvedTokens.dropdownIconExpanded : resolvedTokens.dropdownIcon;
141
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
142
+ style: [styles.buttonContent, selectButtonContentStyles(resolvedTokens)],
143
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
144
+ style: textStyles,
145
+ children: selectedItem?.label || getCopy('selectTab')
146
+ }), dropdownIcon && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
147
+ icon: dropdownIcon,
148
+ variant: {
149
+ size: 'micro'
150
+ },
151
+ tokens: {
152
+ color: textStyles.color
153
+ }
154
+ })]
155
+ });
156
+ }
157
+ }), isOpen && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Listbox.default.Overlay, {
158
+ overlaidPosition: overlaidPosition,
159
+ maxWidth: 400,
160
+ minWidth: 200,
161
+ isReady: isReady,
162
+ onLayout: onTargetLayout,
163
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Listbox.default, {
164
+ items: listboxItems,
165
+ firstItemRef: targetRef,
166
+ parentRef: sourceRef,
167
+ selectedId: value,
168
+ onClose: handleClose,
169
+ LinkRouter: LinkRouter,
170
+ linkRouterProps: linkRouterProps
171
+ })
172
+ })]
173
+ });
174
+ });
175
+ TabsDropdown.displayName = 'TabsDropdown';
176
+ const dictionaryContentShape = _propTypes.default.shape({
177
+ selectTab: _propTypes.default.string.isRequired
178
+ });
179
+ TabsDropdown.propTypes = {
180
+ ...selectedSystemPropTypes,
181
+ ..._utils.withLinkRouter.propTypes,
182
+ /**
183
+ * Array of tab items
184
+ */
185
+ items: _propTypes.default.arrayOf(_propTypes.default.shape({
186
+ ..._utils.withLinkRouter.propTypes,
187
+ /** URL to navigate to when the tab is pressed */
188
+ href: _propTypes.default.string,
189
+ /** Display text for the tab */
190
+ label: _propTypes.default.string,
191
+ /** Unique identifier for the tab */
192
+ id: _propTypes.default.string,
193
+ /** Reference to the tab element */
194
+ ref: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
195
+ /** Custom render function for the tab content */
196
+ render: _propTypes.default.func
197
+ })),
198
+ /**
199
+ * Current selected tab id
200
+ */
201
+ value: _propTypes.default.string,
202
+ /**
203
+ * Callback for when the selected tab changes
204
+ */
205
+ onChange: _propTypes.default.func,
206
+ /**
207
+ * Custom tokens for the main Tabs container
208
+ */
209
+ tokens: (0, _utils.getTokensPropType)('Tabs'),
210
+ /**
211
+ * Custom tokens for `TabsItem`
212
+ */
213
+ itemTokens: (0, _utils.getTokensPropType)('TabsItem'),
214
+ /**
215
+ * Visual and behavioral variants for the tabs dropdown
216
+ */
217
+ variant: _utils.variantProp.propType,
218
+ /**
219
+ * Select English or French copy for the accessible labels.
220
+ * You may also pass in a custom dictionary object.
221
+ */
222
+ copy: _propTypes.default.oneOfType([_propTypes.default.oneOf(['en', 'fr']), dictionaryContentShape]),
223
+ /**
224
+ * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
225
+ */
226
+ dictionary: _propTypes.default.shape({
227
+ en: dictionaryContentShape,
228
+ fr: dictionaryContentShape
229
+ })
230
+ };
231
+ const styles = _StyleSheet.default.create({
232
+ container: {
233
+ position: 'relative',
234
+ width: '100%'
235
+ },
236
+ pressable: {
237
+ outlineWidth: 0,
238
+ outlineStyle: 'none',
239
+ outlineColor: 'transparent'
240
+ },
241
+ buttonContent: {
242
+ display: 'flex',
243
+ flexDirection: 'row',
244
+ alignItems: 'center',
245
+ justifyContent: 'space-between',
246
+ width: '100%',
247
+ minHeight: 44,
248
+ outline: 'none',
249
+ boxSizing: 'border-box'
250
+ }
251
+ });
252
+ var _default = exports.default = TabsDropdown;
@@ -79,8 +79,10 @@ const selectContainerStyles = _ref3 => {
79
79
  borderRadius,
80
80
  paddingHorizontal: paddingHorizontal - borderWidth,
81
81
  paddingVertical: paddingVertical - borderWidth,
82
- marginHorizontal,
83
- marginVertical
82
+ marginLeft: marginHorizontal,
83
+ marginRight: marginHorizontal,
84
+ marginTop: marginVertical,
85
+ marginBottom: marginVertical
84
86
  };
85
87
  };
86
88
 
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _default = exports.default = {
8
+ en: {
9
+ selectTab: 'Select tab'
10
+ },
11
+ fr: {
12
+ selectTab: 'Sélectionner un onglet'
13
+ }
14
+ };
@@ -13,13 +13,18 @@ var _jsxRuntime = require("react/jsx-runtime");
13
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
14
  /**
15
15
  * Provides an up-to-date viewport value from system-constants, available via the `useViewport` hook
16
+ *
17
+ * @param {React.ReactNode} children - Child components that will have access to viewport context
18
+ * @param {string} [defaultViewport] - Default viewport to use during server-side rendering.
19
+ * Must be one of the viewport keys from system-constants. If not provided, defaults to the smallest viewport.
16
20
  */const ViewportProvider = _ref => {
17
21
  let {
18
- children
22
+ children,
23
+ defaultViewport
19
24
  } = _ref;
20
25
  // Default to the smallest viewport for mobile-first SSR. On client side, this is updated
21
26
  // by useViewportListener in a layout effect before anything is shown to the user.
22
- const [viewport, setViewport] = _react.default.useState(_systemConstants.viewports.keys[0]);
27
+ const [viewport, setViewport] = _react.default.useState(defaultViewport || _systemConstants.viewports.keys[0]);
23
28
  (0, _useViewportListener.default)(setViewport);
24
29
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_useViewport.ViewportContext.Provider, {
25
30
  value: viewport,
@@ -27,6 +32,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
27
32
  });
28
33
  };
29
34
  ViewportProvider.propTypes = {
30
- children: _propTypes.default.node.isRequired
35
+ children: _propTypes.default.node.isRequired,
36
+ defaultViewport: _propTypes.default.oneOf(_systemConstants.viewports.keys)
31
37
  };
32
38
  var _default = exports.default = ViewportProvider;
@@ -44,7 +44,7 @@ var _default = exports.default = {
44
44
  * 1. `tooltip` as a string - The content of the tooltip.
45
45
  * 2. `tooltip` as an object - Tooltip component props to be passed.
46
46
  */
47
- tooltip: _propTypes.default.oneOfType([_shared.default, _propTypes.default.string]),
47
+ tooltip: _propTypes.default.oneOfType([_propTypes.default.shape(_shared.default), _propTypes.default.string]),
48
48
  /**
49
49
  * Use to visually mark an input as valid or invalid.
50
50
  */
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { PortalProvider } from '@gorhom/portal';
4
+ import { viewports } from '@telus-uds/system-constants';
4
5
  import A11yInfoProvider from '../A11yInfoProvider';
5
6
  import ViewportProvider from '../ViewportProvider';
6
7
  import ThemeProvider from '../ThemeProvider';
@@ -17,6 +18,7 @@ const BaseProvider = /*#__PURE__*/React.forwardRef((_ref, _) => {
17
18
  return /*#__PURE__*/_jsx(HydrationProvider, {
18
19
  children: /*#__PURE__*/_jsx(A11yInfoProvider, {
19
20
  children: /*#__PURE__*/_jsx(ViewportProvider, {
21
+ defaultViewport: themeOptions?.defaultViewport,
20
22
  children: /*#__PURE__*/_jsx(ThemeProvider, {
21
23
  defaultTheme: defaultTheme,
22
24
  themeOptions: themeOptions,
@@ -34,7 +36,8 @@ BaseProvider.propTypes = {
34
36
  defaultTheme: ThemeProvider.propTypes?.defaultTheme,
35
37
  themeOptions: PropTypes.shape({
36
38
  forceAbsoluteFontSizing: PropTypes.bool,
37
- forceZIndex: PropTypes.bool
39
+ forceZIndex: PropTypes.bool,
40
+ defaultViewport: PropTypes.oneOf(viewports.keys)
38
41
  })
39
42
  };
40
43
  export default BaseProvider;
@@ -1,16 +1,17 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import Platform from "react-native-web/dist/exports/Platform";
4
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
4
5
  import Text from "react-native-web/dist/exports/Text";
5
6
  import View from "react-native-web/dist/exports/View";
6
7
  import buttonPropTypes, { textAndA11yText } from './propTypes';
7
8
  import ButtonBase from './ButtonBase';
8
- import { useThemeTokensCallback } from '../ThemeProvider';
9
+ import { applyTextStyles, useThemeTokensCallback } from '../ThemeProvider';
9
10
  import { a11yProps, getTokensPropType, focusHandlerProps, resolvePressableState, selectTokens, useInputValue } from '../utils';
10
11
  import Icon from '../Icon';
11
- import { getStackedContent } from '../StackView';
12
12
  import { getPressHandlersWithArgs } from '../utils/pressability';
13
- import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ const FULL_WIDTH_STYLE = 'full';
14
15
  const selectIconTokens = _ref => {
15
16
  let {
16
17
  icon,
@@ -49,6 +50,44 @@ const selectIconTokens = _ref => {
49
50
  }
50
51
  };
51
52
  };
53
+ const selectDescriptionTextStyles = tokens => ({
54
+ ...applyTextStyles({
55
+ fontName: tokens?.descriptionFontName,
56
+ fontSize: tokens?.descriptionFontSize,
57
+ fontWeight: tokens?.descriptionFontWeight,
58
+ fontColor: tokens?.color
59
+ }),
60
+ paddingBottom: tokens?.descriptionTextPaddingBottom
61
+ });
62
+ const selectLeadIconTokens = tokens => ({
63
+ color: tokens?.leadIconColor,
64
+ backgroundColor: tokens?.leadIconBackgroundColor,
65
+ size: tokens?.leadIconSize,
66
+ borderRadius: tokens?.leadIconBorderRadius,
67
+ padding: tokens?.leadIconPadding
68
+ });
69
+ const selectLeadIconContainerStyles = tokens => ({
70
+ paddingTop: tokens?.leadIconContainerPaddingTop,
71
+ paddingBottom: tokens?.leadIconContainerPaddingBottom,
72
+ paddingLeft: tokens?.leadIconContainerPaddingLeft,
73
+ paddingRight: tokens?.leadIconContainerPaddingRight
74
+ });
75
+ const selectTextContainerStyles = tokens => ({
76
+ paddingLeft: tokens?.textPaddingLeft,
77
+ paddingRight: tokens?.textPaddingRight
78
+ });
79
+ const selectStackedContentStyles = (tokens, iconPosition, isFullWidth) => ({
80
+ ...staticStyles.stackedContent,
81
+ gap: tokens?.iconSpace,
82
+ flexDirection: iconPosition === 'left' ? 'row' : 'row-reverse',
83
+ ...(Platform.OS === 'web' && {
84
+ flex: 1
85
+ }),
86
+ ...(isFullWidth && {
87
+ justifyContent: 'space-between',
88
+ flex: 1
89
+ })
90
+ });
52
91
  const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
53
92
  let {
54
93
  value,
@@ -61,8 +100,11 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
61
100
  readOnly = false,
62
101
  children = null,
63
102
  accessibilityRole = 'radio',
103
+ description,
104
+ singleOption,
64
105
  ...props
65
106
  } = _ref2;
107
+ const isFullWidth = variant?.width === FULL_WIDTH_STYLE;
66
108
  const {
67
109
  currentValue: isOpen,
68
110
  setValue: setIsOpen
@@ -78,7 +120,13 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
78
120
  ...variant
79
121
  };
80
122
  const getTokens = useThemeTokensCallback('ButtonDropdown', tokens, extraState);
81
- const getButtonTokens = buttonState => selectTokens('Button', getTokens(buttonState));
123
+ const getButtonTokens = buttonState => ({
124
+ ...selectTokens('Button', getTokens(buttonState)),
125
+ iconSpace: props?.icon ? getTokens(buttonState)?.iconSpace : 0,
126
+ ...(isFullWidth && {
127
+ width: 'full'
128
+ })
129
+ });
82
130
 
83
131
  // Pass an object of relevant component state as first argument for any passed-in press handlers
84
132
  const pressHandlers = getPressHandlersWithArgs(props, [{
@@ -96,7 +144,7 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
96
144
  ...pressHandlers,
97
145
  onPress: handlePress,
98
146
  tokens: getButtonTokens,
99
- inactive: inactive,
147
+ inactive: singleOption || inactive,
100
148
  icon: () => null,
101
149
  accessibilityRole: accessibilityRole,
102
150
  ...props,
@@ -112,14 +160,14 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
112
160
  // - Token sets: https://github.com/telus/universal-design-system/issues/782
113
161
 
114
162
  const itemTokens = getTokens(buttonState);
163
+ const leadIcon = itemTokens?.leadIcon;
115
164
  const {
116
165
  iconTokens,
117
166
  iconPosition,
118
- iconSpace,
119
167
  iconWrapperStyle,
120
168
  icon: IconComponent
121
169
  } = selectIconTokens(itemTokens);
122
- const iconContent = IconComponent ? /*#__PURE__*/_jsx(View, {
170
+ const iconContent = IconComponent && !singleOption ? /*#__PURE__*/_jsx(View, {
123
171
  style: iconWrapperStyle,
124
172
  children: /*#__PURE__*/_jsx(Icon, {
125
173
  icon: IconComponent,
@@ -130,13 +178,28 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
130
178
  ...resolvePressableState(buttonState, extraState),
131
179
  textStyles
132
180
  }) : children;
133
- const content = children ? childrenContent() : /*#__PURE__*/_jsx(Text, {
134
- style: textStyles,
135
- children: label
181
+ const content = children ? childrenContent() : /*#__PURE__*/_jsxs(View, {
182
+ style: staticStyles.contentContainer,
183
+ children: [leadIcon && /*#__PURE__*/_jsx(View, {
184
+ style: selectLeadIconContainerStyles(itemTokens),
185
+ children: /*#__PURE__*/_jsx(Icon, {
186
+ icon: leadIcon,
187
+ tokens: selectLeadIconTokens(itemTokens)
188
+ })
189
+ }), /*#__PURE__*/_jsxs(View, {
190
+ style: [staticStyles.textContainer, selectTextContainerStyles(itemTokens)],
191
+ children: [/*#__PURE__*/_jsx(Text, {
192
+ style: textStyles,
193
+ children: label
194
+ }), description && /*#__PURE__*/_jsx(Text, {
195
+ style: selectDescriptionTextStyles(itemTokens),
196
+ children: description
197
+ })]
198
+ })]
136
199
  });
137
- return getStackedContent(iconPosition === 'left' ? [iconContent, content] : [content, iconContent], {
138
- space: iconSpace,
139
- direction: 'row'
200
+ return /*#__PURE__*/_jsxs(View, {
201
+ style: selectStackedContentStyles(itemTokens, iconPosition, isFullWidth),
202
+ children: [iconContent, content]
140
203
  });
141
204
  }
142
205
  });
@@ -168,6 +231,36 @@ ButtonDropdown.propTypes = {
168
231
  /**
169
232
  * By default, `ButtonDropdown` is treated by accessibility tools as a radio button.
170
233
  */
171
- accessibilityRole: PropTypes.string
234
+ accessibilityRole: PropTypes.string,
235
+ /**
236
+ * The description of ButtonDropdown.
237
+ */
238
+ description: PropTypes.string,
239
+ /**
240
+ * Use this prop to render the ButtonDropdown as display only without any interaction when there is only one option.
241
+ */
242
+ singleOption: PropTypes.bool
172
243
  };
244
+ const staticStyles = StyleSheet.create({
245
+ textContainer: {
246
+ alignItems: 'flex-start',
247
+ flexShrink: 1,
248
+ ...(Platform.OS === 'web' && {
249
+ flex: 1
250
+ })
251
+ },
252
+ contentContainer: {
253
+ flexDirection: 'row',
254
+ alignContent: 'center',
255
+ alignItems: 'center',
256
+ ...(Platform.OS === 'web' && {
257
+ flex: 1
258
+ }),
259
+ flexShrink: 1
260
+ },
261
+ stackedContent: {
262
+ flexDirection: 'row',
263
+ alignItems: 'center'
264
+ }
265
+ });
173
266
  export default ButtonDropdown;
@@ -5,7 +5,7 @@ import { useThemeTokens, useThemeTokensCallback, useResponsiveThemeTokens, useTh
5
5
  import { getTokensPropType, variantProp, StyleSheet, createMediaQueryStyles } from '../utils';
6
6
  import { useViewport } from '../ViewportProvider';
7
7
  import { a11yProps, linkProps, selectSystemProps, viewProps, responsiveProps, hrefAttrsProp } from '../utils/props';
8
- import CardBase from './CardBase';
8
+ import CardBase, { selectStyles } from './CardBase';
9
9
  import PressableCardBase from './PressableCardBase';
10
10
  import CheckboxButton from '../Checkbox/CheckboxButton';
11
11
  import RadioButton from '../Radio/RadioButton';
@@ -182,12 +182,27 @@ const Card = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
182
182
  let cardStyles;
183
183
  let mediaIds;
184
184
  if (enableMediaQueryStyleSheet) {
185
- const mediaQueryStyleSheet = createMediaQueryStyles(themeTokens);
185
+ const transformedThemeTokens = Object.entries(themeTokens).reduce((acc, _ref4) => {
186
+ let [vp, viewportTokens] = _ref4;
187
+ const tokensToTransform = selectionType ? selectStyles({
188
+ ...viewportTokens,
189
+ paddingTop: 0,
190
+ paddingBottom: 0,
191
+ paddingLeft: 0,
192
+ paddingRight: 0
193
+ }) : selectStyles(viewportTokens);
194
+ acc[vp] = tokensToTransform;
195
+ return acc;
196
+ }, {});
197
+ const mediaQueryStyleSheet = createMediaQueryStyles(transformedThemeTokens);
186
198
  const {
187
199
  ids,
188
200
  styles
189
201
  } = StyleSheet.create({
190
- card: mediaQueryStyleSheet
202
+ card: {
203
+ ...themeTokens[viewport],
204
+ ...mediaQueryStyleSheet
205
+ }
191
206
  });
192
207
  cardStyles = styles.card;
193
208
  mediaIds = ids.card;
@@ -321,7 +336,9 @@ Card.propTypes = {
321
336
  // src is an object when used responsively to provide different image sources for different screen sizes
322
337
  src: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]).isRequired,
323
338
  alt: PropTypes.string,
324
- resizeMode: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center']))
339
+ resizeMode: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center'])),
340
+ position: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(['bottom', 'left', 'right', 'top'])),
341
+ align: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(['start', 'end', 'center', 'stretch']))
325
342
  }),
326
343
  /**
327
344
  * Data set for the card.