@telus-uds/components-base 3.12.1 → 3.13.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.
- package/CHANGELOG.md +29 -2
- package/lib/cjs/Button/ButtonDropdown.js +105 -12
- package/lib/cjs/Carousel/Carousel.js +26 -0
- package/lib/cjs/Carousel/CarouselContext.js +7 -4
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +13 -2
- package/lib/cjs/Carousel/Constants.js +2 -1
- package/lib/cjs/ExpandCollapse/ExpandCollapse.js +3 -1
- package/lib/cjs/ExpandCollapseMini/ExpandCollapseMini.js +1 -1
- package/lib/cjs/ExpandCollapseMini/ExpandCollapseMiniControl.js +30 -6
- package/lib/cjs/FlexGrid/FlexGrid.js +54 -5
- package/lib/cjs/Icon/Icon.js +3 -1
- package/lib/cjs/InputLabel/InputLabel.js +1 -1
- package/lib/cjs/InputSupports/InputSupports.js +1 -1
- package/lib/cjs/Notification/Notification.js +27 -8
- package/lib/cjs/utils/props/inputSupportsProps.js +1 -1
- package/lib/esm/Button/ButtonDropdown.js +107 -14
- package/lib/esm/Carousel/Carousel.js +27 -1
- package/lib/esm/Carousel/CarouselContext.js +7 -4
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +13 -2
- package/lib/esm/Carousel/Constants.js +1 -0
- package/lib/esm/ExpandCollapse/ExpandCollapse.js +4 -2
- package/lib/esm/ExpandCollapseMini/ExpandCollapseMini.js +2 -2
- package/lib/esm/ExpandCollapseMini/ExpandCollapseMiniControl.js +30 -6
- package/lib/esm/FlexGrid/FlexGrid.js +55 -6
- package/lib/esm/Icon/Icon.js +3 -1
- package/lib/esm/InputLabel/InputLabel.js +1 -1
- package/lib/esm/InputSupports/InputSupports.js +1 -1
- package/lib/esm/Notification/Notification.js +27 -8
- package/lib/esm/utils/props/inputSupportsProps.js +1 -1
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Button/ButtonDropdown.jsx +109 -16
- package/src/Carousel/Carousel.jsx +30 -0
- package/src/Carousel/CarouselContext.jsx +17 -4
- package/src/Carousel/CarouselItem/CarouselItem.jsx +17 -2
- package/src/Carousel/Constants.js +1 -0
- package/src/ExpandCollapse/ExpandCollapse.jsx +5 -2
- package/src/ExpandCollapseMini/ExpandCollapseMini.jsx +2 -2
- package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +39 -9
- package/src/FlexGrid/FlexGrid.jsx +62 -6
- package/src/Icon/Icon.jsx +3 -1
- package/src/InputLabel/InputLabel.jsx +1 -1
- package/src/InputSupports/InputSupports.jsx +1 -1
- package/src/Notification/Notification.jsx +58 -9
- package/src/utils/props/inputSupportsProps.js +1 -1
|
@@ -16,6 +16,7 @@ var _dictionary = _interopRequireDefault(require("./dictionary"));
|
|
|
16
16
|
var _ViewportProvider = require("../ViewportProvider");
|
|
17
17
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
18
18
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
|
+
const CONTENT_MAX_WIDTH = 'max';
|
|
19
20
|
const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
|
|
20
21
|
const selectContainerStyles = tokens => ({
|
|
21
22
|
...tokens
|
|
@@ -70,13 +71,13 @@ const selectDismissButtonContainerStyles = _ref4 => {
|
|
|
70
71
|
placeContent: 'start'
|
|
71
72
|
};
|
|
72
73
|
};
|
|
73
|
-
const selectContentContainerStyle = (themeTokens, maxWidth, system, viewport) => ({
|
|
74
|
-
maxWidth: system && viewport === 'xl' ? maxWidth : '100%',
|
|
74
|
+
const selectContentContainerStyle = (themeTokens, maxWidth, system, viewport, useContentMaxWidth) => ({
|
|
75
|
+
maxWidth: system && (useContentMaxWidth || viewport === 'xl') ? maxWidth : '100%',
|
|
75
76
|
width: '100%',
|
|
76
77
|
paddingRight: themeTokens?.containerPaddingRight,
|
|
77
78
|
paddingLeft: themeTokens?.containerPaddingLeft
|
|
78
79
|
});
|
|
79
|
-
const getMediaQueryStyles = (themeTokens, themeOptions, maxWidth, mediaIdsRef, dismissible, viewport, system) => {
|
|
80
|
+
const getMediaQueryStyles = (themeTokens, themeOptions, maxWidth, mediaIdsRef, dismissible, viewport, system, useContentMaxWidth) => {
|
|
80
81
|
const transformedSelectContainerStyles = Object.entries(themeTokens).reduce((acc, _ref5) => {
|
|
81
82
|
let [vp, viewportTokens] = _ref5;
|
|
82
83
|
acc[vp] = {
|
|
@@ -99,7 +100,7 @@ const getMediaQueryStyles = (themeTokens, themeOptions, maxWidth, mediaIdsRef, d
|
|
|
99
100
|
const transformedSelectContentContainerStyles = Object.entries(themeTokens).reduce((acc, _ref6) => {
|
|
100
101
|
let [vp, viewportTokens] = _ref6;
|
|
101
102
|
acc[vp] = {
|
|
102
|
-
...selectContentContainerStyle(viewportTokens, maxWidth, system, vp),
|
|
103
|
+
...selectContentContainerStyle(viewportTokens, maxWidth, system, vp, useContentMaxWidth),
|
|
103
104
|
flexDirection: 'row',
|
|
104
105
|
flexShrink: 1,
|
|
105
106
|
justifyContent: 'space-between',
|
|
@@ -176,7 +177,7 @@ const getMediaQueryStyles = (themeTokens, themeOptions, maxWidth, mediaIdsRef, d
|
|
|
176
177
|
selectDismissIconPropsStyles
|
|
177
178
|
};
|
|
178
179
|
};
|
|
179
|
-
const getDefaultStyles = (themeTokens, themeOptions, maxWidth, dismissible, viewport, system) => ({
|
|
180
|
+
const getDefaultStyles = (themeTokens, themeOptions, maxWidth, dismissible, viewport, system, useContentMaxWidth) => ({
|
|
180
181
|
containerStyles: {
|
|
181
182
|
container: {
|
|
182
183
|
flexDirection: 'column',
|
|
@@ -188,7 +189,7 @@ const getDefaultStyles = (themeTokens, themeOptions, maxWidth, dismissible, view
|
|
|
188
189
|
flexDirection: 'row',
|
|
189
190
|
flexShrink: 1,
|
|
190
191
|
justifyContent: 'space-between',
|
|
191
|
-
...selectContentContainerStyle(themeTokens, maxWidth, system, viewport),
|
|
192
|
+
...selectContentContainerStyle(themeTokens, maxWidth, system, viewport, useContentMaxWidth),
|
|
192
193
|
...(system && {
|
|
193
194
|
alignSelf: 'center'
|
|
194
195
|
})
|
|
@@ -287,6 +288,7 @@ const Notification = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
|
|
|
287
288
|
tokens,
|
|
288
289
|
variant,
|
|
289
290
|
onDismiss,
|
|
291
|
+
contentMinWidth,
|
|
290
292
|
...rest
|
|
291
293
|
} = _ref7;
|
|
292
294
|
const [isDismissed, setIsDismissed] = _react.default.useState(false);
|
|
@@ -309,6 +311,7 @@ const Notification = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
|
|
|
309
311
|
system: isSystemEnabled,
|
|
310
312
|
viewport
|
|
311
313
|
});
|
|
314
|
+
const useContentMaxWidth = (0, _utils.useResponsiveProp)(contentMinWidth) === CONTENT_MAX_WIDTH;
|
|
312
315
|
const maxWidth = (0, _utils.useResponsiveProp)(themeOptions?.contentMaxWidth, _systemConstants.viewports.map.get(_systemConstants.viewports.xl));
|
|
313
316
|
const notificationComponentRef = _react.default.useRef({
|
|
314
317
|
containerStyles: {},
|
|
@@ -331,9 +334,9 @@ const Notification = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
|
|
|
331
334
|
selectDismissIconPropsIds: {}
|
|
332
335
|
});
|
|
333
336
|
if (enableMediaQueryStyleSheet) {
|
|
334
|
-
notificationComponentRef.current = getMediaQueryStyles(themeTokens, themeOptions, maxWidth, mediaIdsRef, dismissible, viewport, isSystemEnabled);
|
|
337
|
+
notificationComponentRef.current = getMediaQueryStyles(themeTokens, themeOptions, maxWidth, mediaIdsRef, dismissible, viewport, isSystemEnabled, useContentMaxWidth);
|
|
335
338
|
} else {
|
|
336
|
-
notificationComponentRef.current = getDefaultStyles(themeTokens, themeOptions, maxWidth, dismissible, viewport, isSystemEnabled);
|
|
339
|
+
notificationComponentRef.current = getDefaultStyles(themeTokens, themeOptions, maxWidth, dismissible, viewport, isSystemEnabled, useContentMaxWidth);
|
|
337
340
|
}
|
|
338
341
|
if (isDismissed) {
|
|
339
342
|
return null;
|
|
@@ -430,6 +433,22 @@ Notification.propTypes = {
|
|
|
430
433
|
* Callback function called when the dismiss button is clicked
|
|
431
434
|
*/
|
|
432
435
|
onDismiss: _propTypes.default.func,
|
|
436
|
+
/**
|
|
437
|
+
* The minimum width of the content in the Notification when using the system variant.
|
|
438
|
+
* This prop accepts responsive values for different viewports.
|
|
439
|
+
* - `xs`: 'max' | 'full'
|
|
440
|
+
* - `sm`: 'max' | 'full'
|
|
441
|
+
* - `md`: 'max' | 'full'
|
|
442
|
+
* - `lg`: 'max' | 'full'
|
|
443
|
+
* - `xl`: 'max' | 'full'
|
|
444
|
+
*/
|
|
445
|
+
contentMinWidth: _propTypes.default.shape({
|
|
446
|
+
xl: _propTypes.default.oneOf(['max', 'full']),
|
|
447
|
+
lg: _propTypes.default.oneOf(['max', 'full']),
|
|
448
|
+
md: _propTypes.default.oneOf(['max', 'full']),
|
|
449
|
+
sm: _propTypes.default.oneOf(['max', 'full']),
|
|
450
|
+
xs: _propTypes.default.oneOf(['max', 'full'])
|
|
451
|
+
}),
|
|
433
452
|
tokens: (0, _utils.getTokensPropType)('Notification'),
|
|
434
453
|
variant: _utils.variantProp.propType
|
|
435
454
|
};
|
|
@@ -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,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 =>
|
|
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__*/
|
|
134
|
-
style:
|
|
135
|
-
children:
|
|
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
|
|
138
|
-
|
|
139
|
-
|
|
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;
|
|
@@ -21,7 +21,7 @@ import CarouselTabsPanel from './CarouselTabs/CarouselTabsPanel';
|
|
|
21
21
|
import CarouselTabsPanelItem from './CarouselTabs/CarouselTabsPanelItem';
|
|
22
22
|
import dictionary from './dictionary';
|
|
23
23
|
import Box from '../Box';
|
|
24
|
-
import { ITEMS_PER_VIEWPORT_MD, ITEMS_PER_VIEWPORT_LG_XL, DEFAULT_POSITION_OFFSET, LARGE_VIEWPORT_MARGIN, DEFAULT_VIEWPORT_MARGIN, PEEKING_MULTIPLIER, ACTIVE_INDEX_OFFSET_MULTIPLIER, NEGATIVE_MULTIPLIER } from './Constants';
|
|
24
|
+
import { ITEMS_PER_VIEWPORT_XS_SM, ITEMS_PER_VIEWPORT_MD, ITEMS_PER_VIEWPORT_LG_XL, DEFAULT_POSITION_OFFSET, LARGE_VIEWPORT_MARGIN, DEFAULT_VIEWPORT_MARGIN, PEEKING_MULTIPLIER, ACTIVE_INDEX_OFFSET_MULTIPLIER, NEGATIVE_MULTIPLIER } from './Constants';
|
|
25
25
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
26
26
|
const TRANSITION_MODES = {
|
|
27
27
|
MANUAL: 'manual',
|
|
@@ -165,6 +165,31 @@ const getTotalItems = (enableDisplayMultipleItemsPerSlide, childrenArray, viewpo
|
|
|
165
165
|
}
|
|
166
166
|
return childrenArray.length;
|
|
167
167
|
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Determines the maximum number of items that can be displayed per slide based on viewport
|
|
171
|
+
*
|
|
172
|
+
* @param {boolean} enableDisplayMultipleItemsPerSlide - Flag indicating whether multiple items per slide is enabled
|
|
173
|
+
* @param {string} viewport - The current viewport size ('xs', 'sm', 'md', 'lg', 'xl')
|
|
174
|
+
* @returns {number} The maximum number of items that can be displayed per slide
|
|
175
|
+
*/
|
|
176
|
+
const getMaximumItemsForSlide = (enableDisplayMultipleItemsPerSlide, viewport) => {
|
|
177
|
+
if (enableDisplayMultipleItemsPerSlide) {
|
|
178
|
+
switch (viewport) {
|
|
179
|
+
case 'xs':
|
|
180
|
+
case 'sm':
|
|
181
|
+
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
182
|
+
case 'md':
|
|
183
|
+
return ITEMS_PER_VIEWPORT_MD;
|
|
184
|
+
case 'lg':
|
|
185
|
+
case 'xl':
|
|
186
|
+
return ITEMS_PER_VIEWPORT_LG_XL;
|
|
187
|
+
default:
|
|
188
|
+
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
192
|
+
};
|
|
168
193
|
const selectRootContainerStyles = (enableHero, viewport) => {
|
|
169
194
|
if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
|
|
170
195
|
return {
|
|
@@ -860,6 +885,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
860
885
|
firstFocusRef: firstFocusRef,
|
|
861
886
|
refocus: refocus,
|
|
862
887
|
width: containerLayout.width,
|
|
888
|
+
maximumItemsForSlide: getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport),
|
|
863
889
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
864
890
|
style: [staticStyles.root, {
|
|
865
891
|
...(Platform.OS === 'web' ? {
|
|
@@ -13,7 +13,8 @@ const CarouselProvider = _ref => {
|
|
|
13
13
|
refocus = false,
|
|
14
14
|
themeTokens,
|
|
15
15
|
totalItems,
|
|
16
|
-
width
|
|
16
|
+
width,
|
|
17
|
+
maximumItemsForSlide
|
|
17
18
|
} = _ref;
|
|
18
19
|
const value = React.useMemo(() => ({
|
|
19
20
|
activeIndex,
|
|
@@ -23,8 +24,9 @@ const CarouselProvider = _ref => {
|
|
|
23
24
|
refocus,
|
|
24
25
|
themeTokens,
|
|
25
26
|
totalItems,
|
|
26
|
-
width
|
|
27
|
-
|
|
27
|
+
width,
|
|
28
|
+
maximumItemsForSlide
|
|
29
|
+
}), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width, maximumItemsForSlide]);
|
|
28
30
|
return /*#__PURE__*/_jsx(CarouselContext.Provider, {
|
|
29
31
|
value: value,
|
|
30
32
|
children: children
|
|
@@ -46,6 +48,7 @@ CarouselProvider.propTypes = {
|
|
|
46
48
|
refocus: PropTypes.bool,
|
|
47
49
|
themeTokens: getTokensPropType('Carousel'),
|
|
48
50
|
totalItems: PropTypes.number.isRequired,
|
|
49
|
-
width: PropTypes.number.isRequired
|
|
51
|
+
width: PropTypes.number.isRequired,
|
|
52
|
+
maximumItemsForSlide: PropTypes.number
|
|
50
53
|
};
|
|
51
54
|
export { CarouselProvider, useCarousel };
|
|
@@ -87,13 +87,23 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
87
87
|
} = _ref2;
|
|
88
88
|
const {
|
|
89
89
|
width,
|
|
90
|
-
activeIndex
|
|
90
|
+
activeIndex,
|
|
91
|
+
goTo,
|
|
92
|
+
maximumItemsForSlide
|
|
91
93
|
} = useCarousel();
|
|
92
94
|
const selectedProps = selectProps({
|
|
93
95
|
...rest,
|
|
94
96
|
...getA11yPropsFromHtmlTag(tag, rest.accessibilityRole)
|
|
95
97
|
});
|
|
96
|
-
const focusabilityProps = activeIndex === elementIndex ? {} : a11yProps.nonFocusableProps;
|
|
98
|
+
const focusabilityProps = activeIndex === elementIndex || enablePeeking ? {} : a11yProps.nonFocusableProps;
|
|
99
|
+
const handleFocus = React.useCallback(event => {
|
|
100
|
+
if (Platform.OS === 'web' && elementIndex >= maximumItemsForSlide * (activeIndex + 1)) {
|
|
101
|
+
goTo(activeIndex + 1);
|
|
102
|
+
}
|
|
103
|
+
if (rest.onFocus) {
|
|
104
|
+
rest.onFocus(event);
|
|
105
|
+
}
|
|
106
|
+
}, [elementIndex, activeIndex, goTo, maximumItemsForSlide, rest]);
|
|
97
107
|
return /*#__PURE__*/_jsx(View, {
|
|
98
108
|
style: selectContainerStyle({
|
|
99
109
|
width,
|
|
@@ -107,6 +117,7 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
107
117
|
...selectedProps,
|
|
108
118
|
...focusabilityProps,
|
|
109
119
|
ref: ref,
|
|
120
|
+
onFocus: handleFocus,
|
|
110
121
|
children: children
|
|
111
122
|
});
|
|
112
123
|
});
|
|
@@ -3,7 +3,7 @@ import View from "react-native-web/dist/exports/View";
|
|
|
3
3
|
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
5
|
import { useThemeTokens } from '../ThemeProvider';
|
|
6
|
-
import { a11yProps, getTokensPropType, selectSystemProps, useMultipleInputValues, variantProp, viewProps, contentfulProps } from '../utils';
|
|
6
|
+
import { a11yProps, getTokensPropType, selectSystemProps, useMultipleInputValues, variantProp, viewProps, contentfulProps, useUniqueId } from '../utils';
|
|
7
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
8
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps, contentfulProps]);
|
|
9
9
|
function selectBorderStyles(tokens) {
|
|
@@ -33,6 +33,7 @@ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
33
33
|
dataSet,
|
|
34
34
|
...rest
|
|
35
35
|
} = _ref;
|
|
36
|
+
const instanceId = useUniqueId('ExpandCollapse');
|
|
36
37
|
const {
|
|
37
38
|
currentValues: openIds,
|
|
38
39
|
toggleOneValue: onToggle,
|
|
@@ -58,7 +59,8 @@ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
58
59
|
onToggle,
|
|
59
60
|
resetValues,
|
|
60
61
|
setValues,
|
|
61
|
-
unsetValues
|
|
62
|
+
unsetValues,
|
|
63
|
+
instanceId
|
|
62
64
|
}) : children
|
|
63
65
|
})
|
|
64
66
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import ExpandCollapse from '../ExpandCollapse';
|
|
4
|
-
import { getTokensPropType, selectSystemProps, contentfulProps } from '../utils';
|
|
4
|
+
import { getTokensPropType, selectSystemProps, contentfulProps, useUniqueId } from '../utils';
|
|
5
5
|
import { variantProp } from '../utils/props';
|
|
6
6
|
import ExpandCollapseMiniControl from './ExpandCollapseMiniControl';
|
|
7
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -16,7 +16,7 @@ const ExpandCollapseMini = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
16
16
|
dataSet,
|
|
17
17
|
...rest
|
|
18
18
|
} = _ref;
|
|
19
|
-
const expandCollapeMiniPanelId = 'ExpandCollapseMiniPanel';
|
|
19
|
+
const expandCollapeMiniPanelId = useUniqueId('ExpandCollapseMiniPanel');
|
|
20
20
|
const handleChange = (openPanels, event) => {
|
|
21
21
|
if (typeof onToggle === 'function') {
|
|
22
22
|
const isOpen = openPanels.length > 0;
|
|
@@ -45,7 +45,9 @@ const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
45
45
|
pressed
|
|
46
46
|
});
|
|
47
47
|
const {
|
|
48
|
-
|
|
48
|
+
fontSize,
|
|
49
|
+
lineHeight,
|
|
50
|
+
iconSize,
|
|
49
51
|
icon
|
|
50
52
|
} = useThemeTokens('ExpandCollapseMiniControl', tokens, variant, {
|
|
51
53
|
expanded,
|
|
@@ -62,18 +64,38 @@ const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
62
64
|
hover: linkHover
|
|
63
65
|
} = linkState || {};
|
|
64
66
|
const isHovered = hover || linkHover;
|
|
67
|
+
const iconBaselineOffset = 0;
|
|
68
|
+
const hoverTranslateY = 4;
|
|
69
|
+
|
|
70
|
+
// Calculate baseline alignment to vertically center icon with text
|
|
71
|
+
// This combines font and icon metrics with adjustments for visual balance
|
|
72
|
+
const fontBaseline = fontSize / hoverTranslateY; // Quarter of font size - adjusts for text's visual center point
|
|
73
|
+
const iconBaseline = iconSize / hoverTranslateY; // Quarter of icon size - adjusts for icon's visual center point
|
|
74
|
+
const staticOffset = hoverTranslateY; // Fixed downward adjustment to fine-tune vertical alignment
|
|
75
|
+
const sizeCompensation = -Math.abs(iconSize - fontSize); // Compensates when icon and text sizes differ significantly
|
|
76
|
+
|
|
77
|
+
const baselineAlignment = fontBaseline + iconBaseline - staticOffset + sizeCompensation;
|
|
65
78
|
if (Platform.OS !== 'web') {
|
|
79
|
+
// For native platforms, use baseline alignment with optional offset
|
|
66
80
|
return {
|
|
67
|
-
iconTranslateY:
|
|
81
|
+
iconTranslateY: baselineAlignment + iconBaselineOffset
|
|
68
82
|
};
|
|
69
83
|
}
|
|
70
84
|
if (isHovered) {
|
|
71
|
-
//
|
|
85
|
+
// Apply animation offset to the baseline-aligned position
|
|
86
|
+
// When expanded: move icon UP (1.3 the hover distance for clear movement)
|
|
87
|
+
// When collapsed: move icon DOWN (single hover distance)
|
|
88
|
+
const hoverMovementDistance = 1.3;
|
|
89
|
+
const animationOffset = expanded ? -(hoverTranslateY * hoverMovementDistance) : hoverTranslateY;
|
|
72
90
|
return {
|
|
73
|
-
iconTranslateY:
|
|
91
|
+
iconTranslateY: baselineAlignment + iconBaselineOffset + animationOffset
|
|
74
92
|
};
|
|
75
93
|
}
|
|
76
|
-
|
|
94
|
+
|
|
95
|
+
// Default state uses baseline alignment with optional offset
|
|
96
|
+
return {
|
|
97
|
+
iconTranslateY: baselineAlignment + iconBaselineOffset
|
|
98
|
+
};
|
|
77
99
|
};
|
|
78
100
|
return /*#__PURE__*/_jsx(Link, {
|
|
79
101
|
variant: appearance,
|
|
@@ -81,7 +103,9 @@ const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
81
103
|
iconPosition: iconPosition,
|
|
82
104
|
tokens: linkState => ({
|
|
83
105
|
...linkTokens,
|
|
84
|
-
...getTokens(linkState)
|
|
106
|
+
...getTokens(linkState),
|
|
107
|
+
iconSize,
|
|
108
|
+
blockLineHeight: lineHeight
|
|
85
109
|
}),
|
|
86
110
|
ref: ref,
|
|
87
111
|
...presentationOnly,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { viewports } from '@telus-uds/system-constants';
|
|
4
|
-
import { a11yProps, viewProps, getA11yPropsFromHtmlTag, layoutTags, selectSystemProps, BaseView, StyleSheet, createMediaQueryStyles } from '../utils';
|
|
4
|
+
import { a11yProps, viewProps, getA11yPropsFromHtmlTag, layoutTags, selectSystemProps, BaseView, StyleSheet, createMediaQueryStyles, useResponsiveProp } from '../utils';
|
|
5
5
|
import Row from './Row';
|
|
6
6
|
import Col from './Col';
|
|
7
7
|
import GutterContext from './providers/GutterContext';
|
|
@@ -10,6 +10,32 @@ import { useTheme } from '../ThemeProvider';
|
|
|
10
10
|
import { useViewport } from '../ViewportProvider';
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
12
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
13
|
+
const CONTENT_MAX_WIDTH = 'max';
|
|
14
|
+
const CONTENT_FULL_WIDTH = 'full';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolves the maximum width for content based on the provided value and responsive width.
|
|
18
|
+
*
|
|
19
|
+
* @param {number|string|null|undefined} contentMinWidthValue - The minimum width value for the content.
|
|
20
|
+
* Can be a number (pixels), a string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
|
|
21
|
+
* @param {number|string} responsiveWidth - The responsive width to use when contentMinWidthValue is CONTENT_MAX_WIDTH.
|
|
22
|
+
* @returns {number|string|null} The resolved maximum width value, which can be a number, a string (e.g., '100%'), or null.
|
|
23
|
+
*/
|
|
24
|
+
const resolveContentMaxWidth = (contentMinWidthValue, responsiveWidth) => {
|
|
25
|
+
if (!contentMinWidthValue) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (contentMinWidthValue === CONTENT_FULL_WIDTH) {
|
|
29
|
+
return '100%';
|
|
30
|
+
}
|
|
31
|
+
if (Number.isFinite(contentMinWidthValue)) {
|
|
32
|
+
return contentMinWidthValue;
|
|
33
|
+
}
|
|
34
|
+
if (contentMinWidthValue === CONTENT_MAX_WIDTH) {
|
|
35
|
+
return responsiveWidth;
|
|
36
|
+
}
|
|
37
|
+
return contentMinWidthValue;
|
|
38
|
+
};
|
|
13
39
|
|
|
14
40
|
/**
|
|
15
41
|
* A mobile-first flexbox grid.
|
|
@@ -29,35 +55,41 @@ const FlexGrid = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
29
55
|
accessibilityRole,
|
|
30
56
|
children,
|
|
31
57
|
dataSet,
|
|
58
|
+
contentMinWidth,
|
|
32
59
|
...rest
|
|
33
60
|
} = _ref;
|
|
34
61
|
const reverseLevel = applyInheritance([xsReverse, smReverse, mdReverse, lgReverse, xlReverse]);
|
|
35
62
|
const viewport = useViewport();
|
|
36
63
|
const {
|
|
64
|
+
themeOptions,
|
|
37
65
|
themeOptions: {
|
|
38
66
|
enableMediaQueryStyleSheet
|
|
39
67
|
}
|
|
40
68
|
} = useTheme();
|
|
41
69
|
let flexgridStyles;
|
|
42
70
|
let mediaIds;
|
|
71
|
+
const contentMinWidthValue = useResponsiveProp(contentMinWidth);
|
|
72
|
+
const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth);
|
|
73
|
+
const maxWidth = resolveContentMaxWidth(contentMinWidthValue, responsiveWidth);
|
|
43
74
|
const stylesByViewport = {
|
|
44
75
|
xs: {
|
|
76
|
+
maxWidth: limitWidth ? viewports.map.get('sm') : maxWidth,
|
|
45
77
|
flexDirection: reverseLevel[0] ? 'column-reverse' : 'column'
|
|
46
78
|
},
|
|
47
79
|
sm: {
|
|
48
|
-
maxWidth: limitWidth
|
|
80
|
+
maxWidth: limitWidth ? viewports.map.get('sm') : maxWidth,
|
|
49
81
|
flexDirection: reverseLevel[1] ? 'column-reverse' : 'column'
|
|
50
82
|
},
|
|
51
83
|
md: {
|
|
52
|
-
maxWidth: limitWidth
|
|
84
|
+
maxWidth: limitWidth ? viewports.map.get('md') : maxWidth,
|
|
53
85
|
flexDirection: reverseLevel[2] ? 'column-reverse' : 'column'
|
|
54
86
|
},
|
|
55
87
|
lg: {
|
|
56
|
-
maxWidth: limitWidth
|
|
88
|
+
maxWidth: limitWidth ? viewports.map.get('lg') : maxWidth,
|
|
57
89
|
flexDirection: reverseLevel[3] ? 'column-reverse' : 'column'
|
|
58
90
|
},
|
|
59
91
|
xl: {
|
|
60
|
-
maxWidth: limitWidth
|
|
92
|
+
maxWidth: limitWidth ? viewports.map.get('xl') : maxWidth,
|
|
61
93
|
flexDirection: reverseLevel[4] ? 'column-reverse' : 'column'
|
|
62
94
|
}
|
|
63
95
|
};
|
|
@@ -151,7 +183,24 @@ FlexGrid.propTypes = {
|
|
|
151
183
|
/**
|
|
152
184
|
* The rows and columns of the Grid. Will typically be `FlexGrid.Row` and `FlexGrid.Col` components.
|
|
153
185
|
*/
|
|
154
|
-
children: PropTypes.node.isRequired
|
|
186
|
+
children: PropTypes.node.isRequired,
|
|
187
|
+
/**
|
|
188
|
+
* The minimum width of the content in the FlexGrid.
|
|
189
|
+
* This prop accepts responsive values for different viewports. If a number is provided,
|
|
190
|
+
* it will be the max content width for the desired viewport.
|
|
191
|
+
* - `xs`: 'max' | 'full' | <number>
|
|
192
|
+
* - `sm`: 'max' | 'full' | <number>
|
|
193
|
+
* - `md`: 'max' | 'full' | <number>
|
|
194
|
+
* - `lg`: 'max' | 'full' | <number>
|
|
195
|
+
* - `xl`: 'max' | 'full' | <number>
|
|
196
|
+
*/
|
|
197
|
+
contentMinWidth: PropTypes.shape({
|
|
198
|
+
xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
|
|
199
|
+
lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
|
|
200
|
+
md: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
|
|
201
|
+
sm: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
|
|
202
|
+
xs: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number])
|
|
203
|
+
})
|
|
155
204
|
};
|
|
156
205
|
FlexGrid.Row = Row;
|
|
157
206
|
FlexGrid.Col = Col;
|
package/lib/esm/Icon/Icon.js
CHANGED
|
@@ -32,7 +32,9 @@ const Icon = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
32
32
|
width: themeTokens.size + themeTokens.width * 2,
|
|
33
33
|
// sets the diameter of the circle which is the size of the icon plus twice the general padding established to obtain a perfect circle
|
|
34
34
|
height: themeTokens.size + themeTokens.width * 2
|
|
35
|
-
} : {
|
|
35
|
+
} : {
|
|
36
|
+
padding: themeTokens.padding
|
|
37
|
+
};
|
|
36
38
|
const getIconContentForMobile = () => {
|
|
37
39
|
if (Object.keys(paddingStyles).length) {
|
|
38
40
|
return /*#__PURE__*/_jsx(View, {
|
|
@@ -142,7 +142,7 @@ InputLabel.propTypes = {
|
|
|
142
142
|
/**
|
|
143
143
|
* Content of an optional `Tooltip`. If set, a tooltip button will be shown next to the label.
|
|
144
144
|
*/
|
|
145
|
-
tooltip: PropTypes.oneOfType([tooltipPropTypes, PropTypes.string]),
|
|
145
|
+
tooltip: PropTypes.oneOfType([PropTypes.shape(tooltipPropTypes), PropTypes.string]),
|
|
146
146
|
/**
|
|
147
147
|
* Current number of characterts of an input text.
|
|
148
148
|
*/
|