@telus-uds/components-base 3.20.0 → 3.22.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 +27 -1
- package/lib/cjs/Button/Button.js +10 -3
- package/lib/cjs/Button/ButtonBase.js +53 -5
- package/lib/cjs/Card/PressableCardBase.js +3 -1
- package/lib/cjs/Carousel/Carousel.js +11 -3
- package/lib/cjs/Responsive/ResponsiveWithMediaQueryStyleSheet.js +1 -1
- package/lib/cjs/StackView/StackView.js +62 -12
- package/lib/cjs/Tabs/TabsDropdown.js +4 -5
- package/lib/cjs/ThemeProvider/index.js +9 -1
- package/lib/cjs/ThemeProvider/useResponsiveThemeTokensCallback.js +124 -0
- package/lib/cjs/index.js +7 -0
- package/lib/cjs/utils/ssr-media-query/index.js +7 -0
- package/lib/cjs/utils/ssr-media-query/utils/use-all-viewport-tokens.js +53 -0
- package/lib/esm/Button/Button.js +11 -4
- package/lib/esm/Button/ButtonBase.js +54 -6
- package/lib/esm/Card/PressableCardBase.js +3 -1
- package/lib/esm/Carousel/Carousel.js +11 -3
- package/lib/esm/Responsive/ResponsiveWithMediaQueryStyleSheet.js +1 -1
- package/lib/esm/StackView/StackView.js +63 -13
- package/lib/esm/Tabs/TabsDropdown.js +4 -5
- package/lib/esm/ThemeProvider/index.js +1 -0
- package/lib/esm/ThemeProvider/useResponsiveThemeTokensCallback.js +117 -0
- package/lib/esm/index.js +1 -1
- package/lib/esm/utils/ssr-media-query/index.js +2 -1
- package/lib/esm/utils/ssr-media-query/utils/use-all-viewport-tokens.js +48 -0
- package/lib/package.json +4 -4
- package/package.json +4 -4
- package/src/Button/Button.jsx +24 -4
- package/src/Button/ButtonBase.jsx +61 -4
- package/src/Card/PressableCardBase.jsx +3 -1
- package/src/Carousel/Carousel.jsx +13 -2
- package/src/PriceLockup/utils/renderPrice.jsx +15 -17
- package/src/Responsive/ResponsiveWithMediaQueryStyleSheet.jsx +1 -1
- package/src/StackView/StackView.jsx +62 -9
- package/src/Tabs/TabsDropdown.jsx +10 -9
- package/src/ThemeProvider/index.js +1 -0
- package/src/ThemeProvider/useResponsiveThemeTokensCallback.js +129 -0
- package/src/index.js +2 -1
- package/src/utils/ssr-media-query/index.js +2 -1
- package/src/utils/ssr-media-query/utils/use-all-viewport-tokens.js +32 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-base
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Wed, 29 Oct 2025 07:40:46 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 3.22.0
|
|
8
|
+
|
|
9
|
+
Wed, 29 Oct 2025 07:40:46 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- `Carousel`: Add `loopDuration` prop (oscar.palencia@telus.com)
|
|
14
|
+
- `Button`: add RNMQ support (guillermo.peitzner@telus.com)
|
|
15
|
+
|
|
16
|
+
### Patches
|
|
17
|
+
|
|
18
|
+
- `Interactive Card`: extra spacing fixed in interactive Cards when padding tokens are set to none (35577399+JoshHC@users.noreply.github.com)
|
|
19
|
+
|
|
20
|
+
## 3.21.0
|
|
21
|
+
|
|
22
|
+
Tue, 21 Oct 2025 14:46:26 GMT
|
|
23
|
+
|
|
24
|
+
### Minor changes
|
|
25
|
+
|
|
26
|
+
- `StackView`: add RNMQ support (guillermo.peitzner@telus.com)
|
|
27
|
+
|
|
28
|
+
### Patches
|
|
29
|
+
|
|
30
|
+
- `Responsive`: fix console warning (guillermo.peitzner@telus.com)
|
|
31
|
+
- `TabsDropdown`: outline unnecessary property removed (35577399+JoshHC@users.noreply.github.com)
|
|
32
|
+
|
|
7
33
|
## 3.20.0
|
|
8
34
|
|
|
9
35
|
Fri, 10 Oct 2025 15:11:05 GMT
|
package/lib/cjs/Button/Button.js
CHANGED
|
@@ -22,16 +22,23 @@ const Button = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
|
|
|
22
22
|
...props
|
|
23
23
|
} = _ref;
|
|
24
24
|
const viewport = (0, _ViewportProvider.useViewport)();
|
|
25
|
-
const
|
|
25
|
+
const {
|
|
26
|
+
themeOptions: {
|
|
27
|
+
enableMediaQueryStyleSheet
|
|
28
|
+
}
|
|
29
|
+
} = (0, _ThemeProvider.useTheme)();
|
|
30
|
+
const buttonVariant = enableMediaQueryStyleSheet ? variant : {
|
|
26
31
|
viewport,
|
|
27
32
|
...variant
|
|
28
33
|
};
|
|
29
|
-
const
|
|
34
|
+
const useTokens = enableMediaQueryStyleSheet ? _ThemeProvider.useResponsiveThemeTokensCallback : _ThemeProvider.useThemeTokensCallback;
|
|
35
|
+
const getTokens = useTokens('Button', tokens, buttonVariant);
|
|
30
36
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ButtonBase.default, {
|
|
31
37
|
...props,
|
|
32
38
|
tokens: getTokens,
|
|
33
39
|
accessibilityRole: accessibilityRole,
|
|
34
|
-
ref: ref
|
|
40
|
+
ref: ref,
|
|
41
|
+
viewport: viewport
|
|
35
42
|
});
|
|
36
43
|
});
|
|
37
44
|
Button.displayName = 'Button';
|
|
@@ -257,6 +257,13 @@ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref12, ref) => {
|
|
|
257
257
|
iconProps,
|
|
258
258
|
...rawRest
|
|
259
259
|
} = _ref12;
|
|
260
|
+
const {
|
|
261
|
+
themeOptions
|
|
262
|
+
} = (0, _ThemeProvider.useTheme)();
|
|
263
|
+
const {
|
|
264
|
+
viewport
|
|
265
|
+
} = rawRest;
|
|
266
|
+
const enableMediaQueryStyleSheet = themeOptions.enableMediaQueryStyleSheet && viewport;
|
|
260
267
|
const {
|
|
261
268
|
onPress,
|
|
262
269
|
...rest
|
|
@@ -268,15 +275,55 @@ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref12, ref) => {
|
|
|
268
275
|
};
|
|
269
276
|
const resolveButtonTokens = pressableState => (0, _utils.resolvePressableTokens)(tokens, pressableState, extraButtonState);
|
|
270
277
|
const systemProps = selectProps(rest);
|
|
278
|
+
let layoutMediaQueryStyles;
|
|
279
|
+
let flexAndWidthStylesIds;
|
|
280
|
+
if (enableMediaQueryStyleSheet) {
|
|
281
|
+
const defaultPressableState = {
|
|
282
|
+
pressed: false,
|
|
283
|
+
hovered: false,
|
|
284
|
+
focused: false
|
|
285
|
+
};
|
|
286
|
+
const defaultTokensByViewport = resolveButtonTokens(defaultPressableState);
|
|
287
|
+
const layoutTokensByViewport = Object.entries(defaultTokensByViewport).reduce((acc, _ref13) => {
|
|
288
|
+
let [vp, viewportTokens] = _ref13;
|
|
289
|
+
const flexAndWidthStyles = viewportTokens.width === '100%' && viewportTokens.flex === 1 ? selectFlexAndWidthStyles(viewportTokens) : {};
|
|
290
|
+
acc[vp] = {
|
|
291
|
+
...staticStyles.row,
|
|
292
|
+
...selectWebOnlyStyles(inactive, viewportTokens, systemProps),
|
|
293
|
+
...(Object.keys(flexAndWidthStyles).length > 0 ? flexAndWidthStyles : {}),
|
|
294
|
+
...selectOuterSizeStyles(viewportTokens)
|
|
295
|
+
};
|
|
296
|
+
return acc;
|
|
297
|
+
}, {});
|
|
298
|
+
const mediaQueryStyles = (0, _utils.createMediaQueryStyles)(layoutTokensByViewport);
|
|
299
|
+
const {
|
|
300
|
+
ids,
|
|
301
|
+
styles
|
|
302
|
+
} = _utils.StyleSheet.create({
|
|
303
|
+
layout: {
|
|
304
|
+
...mediaQueryStyles
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
layoutMediaQueryStyles = styles.layout;
|
|
308
|
+
flexAndWidthStylesIds = ids.layout;
|
|
309
|
+
}
|
|
271
310
|
const getPressableStyle = pressableState => {
|
|
311
|
+
if (enableMediaQueryStyleSheet) {
|
|
312
|
+
const themeTokens = resolveButtonTokens(pressableState)[viewport];
|
|
313
|
+
return [layoutMediaQueryStyles, selectOuterContainerStyles(themeTokens)];
|
|
314
|
+
}
|
|
272
315
|
const themeTokens = resolveButtonTokens(pressableState);
|
|
273
|
-
// Only apply flex and width styles when they are explicitly set (e.g., from ButtonGroup with width: 'equal') to not to affect other use cases
|
|
274
316
|
const flexAndWidthStyles = themeTokens.width === '100%' && themeTokens.flex === 1 ? selectFlexAndWidthStyles(themeTokens) : {};
|
|
275
317
|
return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens), ...(Object.keys(flexAndWidthStyles).length > 0 ? [flexAndWidthStyles] : []), selectOuterSizeStyles(themeTokens)];
|
|
276
318
|
};
|
|
277
|
-
const {
|
|
278
|
-
|
|
279
|
-
|
|
319
|
+
const dataSetProp = flexAndWidthStylesIds || rawRest.dataSet ? {
|
|
320
|
+
dataSet: {
|
|
321
|
+
...(flexAndWidthStylesIds ? {
|
|
322
|
+
media: flexAndWidthStylesIds
|
|
323
|
+
} : {}),
|
|
324
|
+
...rawRest.dataSet
|
|
325
|
+
}
|
|
326
|
+
} : {};
|
|
280
327
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pressable.default, {
|
|
281
328
|
ref: ref,
|
|
282
329
|
href: href,
|
|
@@ -288,8 +335,9 @@ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref12, ref) => {
|
|
|
288
335
|
disabled: inactive,
|
|
289
336
|
hrefAttrs: hrefAttrs,
|
|
290
337
|
...systemProps,
|
|
338
|
+
...dataSetProp,
|
|
291
339
|
children: pressableState => {
|
|
292
|
-
const themeTokens = resolveButtonTokens(pressableState);
|
|
340
|
+
const themeTokens = enableMediaQueryStyleSheet ? resolveButtonTokens(pressableState)[viewport] : resolveButtonTokens(pressableState);
|
|
293
341
|
const containerStyles = selectInnerContainerStyles(themeTokens);
|
|
294
342
|
const borderStyles = selectBorderStyles(themeTokens);
|
|
295
343
|
const textStyles = [selectTextStyles(themeTokens, themeOptions), staticStyles.text, _Platform.default.select({
|
|
@@ -181,7 +181,9 @@ const staticStyles = _StyleSheet.default.create({
|
|
|
181
181
|
},
|
|
182
182
|
linkContainer: {
|
|
183
183
|
flex: 1,
|
|
184
|
-
display: 'flex'
|
|
184
|
+
display: 'flex',
|
|
185
|
+
alignItems: 'stretch',
|
|
186
|
+
justifyContent: 'flex-start'
|
|
185
187
|
}
|
|
186
188
|
});
|
|
187
189
|
PressableCardBase.displayName = 'PressableCardBase';
|
|
@@ -358,6 +358,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
|
|
|
358
358
|
copy,
|
|
359
359
|
slideDuration = 0,
|
|
360
360
|
transitionDuration = 0,
|
|
361
|
+
loopDuration = transitionDuration,
|
|
361
362
|
autoPlay = false,
|
|
362
363
|
enablePeeking = false,
|
|
363
364
|
...rest
|
|
@@ -477,6 +478,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
|
|
|
477
478
|
}
|
|
478
479
|
}, [pan, animatedX, heroPan, heroAnimatedX, enableHero, viewport, enablePeeking]);
|
|
479
480
|
const animate = _react.default.useCallback((panToAnimate, toValue, toIndex) => {
|
|
481
|
+
const applicableTransitionDuration = isLastSlide && toIndex === 0 ? loopDuration : transitionDuration;
|
|
480
482
|
const handleAnimationEndToIndex = function () {
|
|
481
483
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
482
484
|
args[_key] = arguments[_key];
|
|
@@ -494,14 +496,14 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
|
|
|
494
496
|
...springConfig,
|
|
495
497
|
toValue,
|
|
496
498
|
useNativeDriver: false,
|
|
497
|
-
duration:
|
|
499
|
+
duration: applicableTransitionDuration * 1000
|
|
498
500
|
}).start(handleAnimationEndToIndex);
|
|
499
501
|
} else if (enablePeeking || enableDisplayMultipleItemsPerSlide) {
|
|
500
502
|
_Animated.default.timing(panToAnimate, {
|
|
501
503
|
...springConfig,
|
|
502
504
|
toValue,
|
|
503
505
|
useNativeDriver: false,
|
|
504
|
-
duration:
|
|
506
|
+
duration: applicableTransitionDuration ? applicableTransitionDuration * 1000 : 1000
|
|
505
507
|
}).start(handleAnimationEndToIndex);
|
|
506
508
|
} else {
|
|
507
509
|
_Animated.default.spring(panToAnimate, {
|
|
@@ -510,7 +512,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
|
|
|
510
512
|
useNativeDriver: false
|
|
511
513
|
}).start(handleAnimationEndToIndex);
|
|
512
514
|
}
|
|
513
|
-
}, [springConfig, handleAnimationEnd, transitionDuration, isAutoPlayEnabled, enablePeeking, enableDisplayMultipleItemsPerSlide]);
|
|
515
|
+
}, [springConfig, handleAnimationEnd, transitionDuration, loopDuration, isLastSlide, isAutoPlayEnabled, enablePeeking, enableDisplayMultipleItemsPerSlide]);
|
|
514
516
|
const stopAutoplay = _react.default.useCallback(() => {
|
|
515
517
|
if (autoPlayRef?.current) {
|
|
516
518
|
clearTimeout(autoPlayRef?.current);
|
|
@@ -1204,6 +1206,12 @@ Carousel.propTypes = {
|
|
|
1204
1206
|
* - `autoPlay` and `slideDuration` are required to be set for this to work
|
|
1205
1207
|
*/
|
|
1206
1208
|
transitionDuration: _propTypes.default.number,
|
|
1209
|
+
/**
|
|
1210
|
+
* Time it takes in seconds to transition from last slide to first slide
|
|
1211
|
+
* - Default value equals `transitionDuration`'s value
|
|
1212
|
+
* - `autoPlay` and `transitionDuration` are required to be set for this to work
|
|
1213
|
+
*/
|
|
1214
|
+
loopDuration: _propTypes.default.number,
|
|
1207
1215
|
/**
|
|
1208
1216
|
* If set to `true`, the Carousel will show the previous and next slides
|
|
1209
1217
|
* - Default value is `false`
|
|
@@ -68,7 +68,7 @@ ResponsiveWithMediaQueryStyleSheet.propTypes = {
|
|
|
68
68
|
/**
|
|
69
69
|
* To hide children of `Responsive` if the current viewport is larger than `max`
|
|
70
70
|
*/
|
|
71
|
-
max: _propTypes.default.oneOf(['sm', 'md', 'lg', 'xl']),
|
|
71
|
+
max: _propTypes.default.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
|
|
72
72
|
inheritedStyles: _propTypes.default.arrayOf(_propTypes.default.string),
|
|
73
73
|
children: _propTypes.default.node.isRequired
|
|
74
74
|
};
|
|
@@ -9,8 +9,7 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
9
9
|
var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
|
|
10
10
|
var _Divider = _interopRequireDefault(require("../Divider"));
|
|
11
11
|
var _utils = require("../utils");
|
|
12
|
-
var
|
|
13
|
-
var _ViewportProvider = require("../ViewportProvider");
|
|
12
|
+
var _useTheme = _interopRequireDefault(require("../ThemeProvider/useTheme"));
|
|
14
13
|
var _getStackedContent = _interopRequireDefault(require("./getStackedContent"));
|
|
15
14
|
var _common = require("./common");
|
|
16
15
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -69,10 +68,15 @@ const StackView = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
|
|
|
69
68
|
tokens,
|
|
70
69
|
tag,
|
|
71
70
|
accessibilityRole,
|
|
71
|
+
dataSet,
|
|
72
72
|
...rest
|
|
73
73
|
} = _ref;
|
|
74
|
-
const viewport = (0, _ViewportProvider.useViewport)();
|
|
75
74
|
const direction = (0, _utils.useResponsiveProp)(directionProp, 'column');
|
|
75
|
+
const {
|
|
76
|
+
themeOptions: {
|
|
77
|
+
enableMediaQueryStyleSheet
|
|
78
|
+
}
|
|
79
|
+
} = (0, _useTheme.default)();
|
|
76
80
|
const selectedProps = selectProps({
|
|
77
81
|
accessibilityRole,
|
|
78
82
|
...(0, _utils.getA11yPropsFromHtmlTag)(tag, accessibilityRole),
|
|
@@ -83,17 +87,58 @@ const StackView = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
|
|
|
83
87
|
divider,
|
|
84
88
|
space
|
|
85
89
|
});
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
const allTokens = (0, _utils.useAllViewportTokens)('StackView', tokens, variant);
|
|
91
|
+
let stackViewStyles;
|
|
92
|
+
let dataSetValue = dataSet;
|
|
93
|
+
if (enableMediaQueryStyleSheet) {
|
|
94
|
+
const stylesByViewport = {
|
|
95
|
+
xs: {
|
|
96
|
+
...(0, _common.selectFlexStyles)(allTokens.xs),
|
|
97
|
+
width: allTokens.xs.width
|
|
98
|
+
},
|
|
99
|
+
sm: {
|
|
100
|
+
...(0, _common.selectFlexStyles)(allTokens.sm),
|
|
101
|
+
width: allTokens.sm.width
|
|
102
|
+
},
|
|
103
|
+
md: {
|
|
104
|
+
...(0, _common.selectFlexStyles)(allTokens.md),
|
|
105
|
+
width: allTokens.md.width
|
|
106
|
+
},
|
|
107
|
+
lg: {
|
|
108
|
+
...(0, _common.selectFlexStyles)(allTokens.lg),
|
|
109
|
+
width: allTokens.lg.width
|
|
110
|
+
},
|
|
111
|
+
xl: {
|
|
112
|
+
...(0, _common.selectFlexStyles)(allTokens.xl),
|
|
113
|
+
width: allTokens.xl.width
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const mediaQueryStyles = (0, _utils.createMediaQueryStyles)(stylesByViewport);
|
|
117
|
+
const {
|
|
118
|
+
ids,
|
|
119
|
+
styles
|
|
120
|
+
} = _utils.StyleSheet.create({
|
|
121
|
+
stackView: {
|
|
122
|
+
...mediaQueryStyles
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
stackViewStyles = [_common.staticStyles[direction], styles.stackView];
|
|
126
|
+
dataSetValue = {
|
|
127
|
+
media: ids.stackView,
|
|
128
|
+
...dataSet
|
|
129
|
+
};
|
|
130
|
+
} else {
|
|
131
|
+
const flexStyles = (0, _common.selectFlexStyles)(allTokens.current);
|
|
132
|
+
const size = {
|
|
133
|
+
width: allTokens.current.width
|
|
134
|
+
};
|
|
135
|
+
stackViewStyles = [flexStyles, _common.staticStyles[direction], size];
|
|
136
|
+
}
|
|
93
137
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
|
|
94
138
|
ref: ref,
|
|
95
139
|
...selectedProps,
|
|
96
|
-
style:
|
|
140
|
+
style: stackViewStyles,
|
|
141
|
+
dataSet: dataSetValue,
|
|
97
142
|
children: content
|
|
98
143
|
});
|
|
99
144
|
});
|
|
@@ -128,6 +173,11 @@ StackView.propTypes = {
|
|
|
128
173
|
* A StackView may take any children, but will have no effect if it is only passed one child or is passed children
|
|
129
174
|
* wrapped in a component. If necessary, children may be wrapped in one React Fragment.
|
|
130
175
|
*/
|
|
131
|
-
children: _propTypes.default.node
|
|
176
|
+
children: _propTypes.default.node,
|
|
177
|
+
/**
|
|
178
|
+
* Data attributes to be applied to the element. When media query stylesheet is enabled,
|
|
179
|
+
* this will include media query IDs for responsive styling.
|
|
180
|
+
*/
|
|
181
|
+
dataSet: _propTypes.default.object
|
|
132
182
|
};
|
|
133
183
|
var _default = exports.default = StackView;
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = _interopRequireDefault(require("react"));
|
|
8
8
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
9
|
+
var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
|
|
9
10
|
var _Pressable = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Pressable"));
|
|
10
11
|
var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
|
|
11
12
|
var _Text = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Text"));
|
|
@@ -233,20 +234,18 @@ const styles = _StyleSheet.default.create({
|
|
|
233
234
|
position: 'relative',
|
|
234
235
|
width: '100%'
|
|
235
236
|
},
|
|
236
|
-
pressable: {
|
|
237
|
+
pressable: _Platform.default.OS === 'web' ? {
|
|
237
238
|
outlineWidth: 0,
|
|
238
239
|
outlineStyle: 'none',
|
|
239
240
|
outlineColor: 'transparent'
|
|
240
|
-
},
|
|
241
|
+
} : {},
|
|
241
242
|
buttonContent: {
|
|
242
243
|
display: 'flex',
|
|
243
244
|
flexDirection: 'row',
|
|
244
245
|
alignItems: 'center',
|
|
245
246
|
justifyContent: 'space-between',
|
|
246
247
|
width: '100%',
|
|
247
|
-
minHeight: 44
|
|
248
|
-
outline: 'none',
|
|
249
|
-
boxSizing: 'border-box'
|
|
248
|
+
minHeight: 44
|
|
250
249
|
}
|
|
251
250
|
});
|
|
252
251
|
var _default = exports.default = TabsDropdown;
|
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
var _exportNames = {
|
|
7
7
|
useTheme: true,
|
|
8
8
|
useSetTheme: true,
|
|
9
|
-
useResponsiveThemeTokens: true
|
|
9
|
+
useResponsiveThemeTokens: true,
|
|
10
|
+
useResponsiveThemeTokensCallback: true
|
|
10
11
|
};
|
|
11
12
|
exports.default = void 0;
|
|
12
13
|
Object.defineProperty(exports, "useResponsiveThemeTokens", {
|
|
@@ -15,6 +16,12 @@ Object.defineProperty(exports, "useResponsiveThemeTokens", {
|
|
|
15
16
|
return _useResponsiveThemeTokens.default;
|
|
16
17
|
}
|
|
17
18
|
});
|
|
19
|
+
Object.defineProperty(exports, "useResponsiveThemeTokensCallback", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () {
|
|
22
|
+
return _useResponsiveThemeTokensCallback.default;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
18
25
|
Object.defineProperty(exports, "useSetTheme", {
|
|
19
26
|
enumerable: true,
|
|
20
27
|
get: function () {
|
|
@@ -31,6 +38,7 @@ var _ThemeProvider = _interopRequireDefault(require("./ThemeProvider"));
|
|
|
31
38
|
var _useTheme = _interopRequireDefault(require("./useTheme"));
|
|
32
39
|
var _useSetTheme = _interopRequireDefault(require("./useSetTheme"));
|
|
33
40
|
var _useResponsiveThemeTokens = _interopRequireDefault(require("./useResponsiveThemeTokens"));
|
|
41
|
+
var _useResponsiveThemeTokensCallback = _interopRequireDefault(require("./useResponsiveThemeTokensCallback"));
|
|
34
42
|
var _useThemeTokens = require("./useThemeTokens");
|
|
35
43
|
Object.keys(_useThemeTokens).forEach(function (key) {
|
|
36
44
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _systemConstants = require("@telus-uds/system-constants");
|
|
9
|
+
var _useTheme = _interopRequireDefault(require("./useTheme"));
|
|
10
|
+
var _utils = require("./utils");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
const getResponsiveThemeTokens = function (_ref, tokensProp) {
|
|
13
|
+
let {
|
|
14
|
+
rules = [],
|
|
15
|
+
tokens: defaultThemeTokens = {}
|
|
16
|
+
} = _ref;
|
|
17
|
+
let variants = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
18
|
+
let states = arguments.length > 3 ? arguments[3] : undefined;
|
|
19
|
+
const appearances = (0, _utils.mergeAppearances)(variants, states);
|
|
20
|
+
const tokensByViewport = Object.fromEntries(_systemConstants.viewports.keys.map(viewport => [viewport, {
|
|
21
|
+
...defaultThemeTokens
|
|
22
|
+
}]));
|
|
23
|
+
|
|
24
|
+
// Go through each rule and collect them for the corresponding viewport if they apply
|
|
25
|
+
rules.forEach(rule => {
|
|
26
|
+
if (doesRuleApply(rule, appearances)) {
|
|
27
|
+
// If the rule does not have a viewport specified, we collect it in all viewports
|
|
28
|
+
let targetViewports = rule.if.viewport || _systemConstants.viewports.keys;
|
|
29
|
+
if (!Array.isArray(targetViewports)) {
|
|
30
|
+
targetViewports = [targetViewports];
|
|
31
|
+
}
|
|
32
|
+
targetViewports.forEach(viewport => {
|
|
33
|
+
tokensByViewport[viewport] = {
|
|
34
|
+
...tokensByViewport[viewport],
|
|
35
|
+
...rule.tokens
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
Object.keys(tokensByViewport).forEach(viewport => {
|
|
41
|
+
tokensByViewport[viewport] = (0, _utils.resolveThemeTokens)(tokensByViewport[viewport], appearances, tokensProp);
|
|
42
|
+
});
|
|
43
|
+
return tokensByViewport;
|
|
44
|
+
};
|
|
45
|
+
const doesRuleApply = (rule, appearances) => Object.entries(rule.if).every(condition => doesConditionApply(condition, appearances));
|
|
46
|
+
const doesConditionApply = (_ref2, appearances) => {
|
|
47
|
+
let [key, value] = _ref2;
|
|
48
|
+
if (key === 'viewport') {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
// use null rather than undefined so we can serialise the value in themes
|
|
52
|
+
const appearanceValue = appearances[key] ?? null;
|
|
53
|
+
return Array.isArray(value) ? value.includes(appearanceValue) : value === appearanceValue;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {import('../utils/props/tokens.js').TokensSet} TokensSet
|
|
58
|
+
* @typedef {import('../utils/props/tokens.js').TokensProp} TokensProp
|
|
59
|
+
* @typedef {import('../utils/props/variantProp').AppearanceSet} AppearanceSet
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Returns a memoised tokens getter function that gets responsive tokens for all viewports,
|
|
64
|
+
* similar to calling useResponsiveThemeTokens but with the callback pattern of useThemeTokensCallback.
|
|
65
|
+
*
|
|
66
|
+
* Scenarios where `useResponsiveThemeTokensCallback` should be used:
|
|
67
|
+
*
|
|
68
|
+
* - Where responsive tokens are to be obtained from state that is accessible only in scopes like callbacks
|
|
69
|
+
* and render functions, where calling useResponsiveThemeTokens directly would be disallowed by React's hook rules.
|
|
70
|
+
* - When using media query stylesheets and need to resolve tokens based on dynamic state (e.g., pressed, hovered)
|
|
71
|
+
* that changes at runtime.
|
|
72
|
+
* - Passing a responsive tokens getter down via a child component's `tokens` prop, applying rules using the
|
|
73
|
+
* child component's current state.
|
|
74
|
+
*
|
|
75
|
+
* The function returned may be called with an object of state appearances to get an object
|
|
76
|
+
* of tokens for each viewport, which can then be passed to createMediaQueryStyles.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Resolving responsive tokens inside Pressable's style function, based on Pressable state
|
|
80
|
+
* const PressMe = ({ tokens, variant, children }) => {
|
|
81
|
+
* const getResponsiveTokens = useResponsiveThemeTokensCallback('PressMe', tokens, variant)
|
|
82
|
+
* const getPressableStyle = ({ pressed }) => {
|
|
83
|
+
* const responsiveTokens = getResponsiveTokens({ pressed })
|
|
84
|
+
* const mediaQueryStyles = createMediaQueryStyles(responsiveTokens)
|
|
85
|
+
* return mediaQueryStyles
|
|
86
|
+
* }
|
|
87
|
+
* return <Pressable style={getPressableStyle}>{children}</Pressable>
|
|
88
|
+
* }
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* // Setting the theme in a parent and resolving it in a child based on child's state
|
|
92
|
+
* const MenuButton = ({ tokens, variant, ...buttonProps }) => {
|
|
93
|
+
* // Define what theme, variant etc we want in this component...
|
|
94
|
+
* const getResponsiveTokens = useResponsiveThemeTokensCallback('Button', tokens, variant)
|
|
95
|
+
* // ...resolve them in another component based on its state (e.g. press, hover...)
|
|
96
|
+
* return <ButtonBase tokens={getResponsiveTokens} accessibilityRole="menuitem" {...buttonProps} />
|
|
97
|
+
* }
|
|
98
|
+
*
|
|
99
|
+
* @typedef {Object} ResponsiveObject
|
|
100
|
+
* @property {TokensSet} xs
|
|
101
|
+
* @property {TokensSet} sm
|
|
102
|
+
* @property {TokensSet} md
|
|
103
|
+
* @property {TokensSet} lg
|
|
104
|
+
* @property {TokensSet} xl
|
|
105
|
+
*
|
|
106
|
+
* @param {string} componentName - the name as defined in the theme schema of the component whose theme is to be used
|
|
107
|
+
* @param {TokensProp} [tokens] - every themed component should accept a `tokens` prop allowing theme tokens to be overridden
|
|
108
|
+
* @param {AppearanceSet} [variants] - variants passed in as props that don't change dynamically
|
|
109
|
+
* @returns {(states: AppearanceSet, tokenOverrides?: TokensProp) => ResponsiveObject}
|
|
110
|
+
* - callback function that returns an overridable responsive tokens object for current state. Only pass
|
|
111
|
+
* tokenOverrides in rare cases where tokens overrides are also generated outside hook scope.
|
|
112
|
+
*/
|
|
113
|
+
const useResponsiveThemeTokensCallback = function (componentName) {
|
|
114
|
+
let tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
115
|
+
let variants = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
116
|
+
const theme = (0, _useTheme.default)();
|
|
117
|
+
const componentTheme = (0, _utils.getComponentTheme)(theme, componentName);
|
|
118
|
+
const getResponsiveThemeTokensCallback = (0, _react.useCallback)((states, tokenOverrides) => {
|
|
119
|
+
const resolvedTokens = (0, _utils.resolveThemeTokens)(tokens, (0, _utils.mergeAppearances)(variants, states), tokenOverrides);
|
|
120
|
+
return getResponsiveThemeTokens(componentTheme, resolvedTokens, variants, states);
|
|
121
|
+
}, [componentTheme, tokens, variants]);
|
|
122
|
+
return getResponsiveThemeTokensCallback;
|
|
123
|
+
};
|
|
124
|
+
var _default = exports.default = useResponsiveThemeTokensCallback;
|
package/lib/cjs/index.js
CHANGED
|
@@ -93,6 +93,7 @@ var _exportNames = {
|
|
|
93
93
|
applyTextStyles: true,
|
|
94
94
|
applyShadowToken: true,
|
|
95
95
|
useResponsiveThemeTokens: true,
|
|
96
|
+
useResponsiveThemeTokensCallback: true,
|
|
96
97
|
Portal: true
|
|
97
98
|
};
|
|
98
99
|
Object.defineProperty(exports, "A11yInfoProvider", {
|
|
@@ -605,6 +606,12 @@ Object.defineProperty(exports, "useResponsiveThemeTokens", {
|
|
|
605
606
|
return _ThemeProvider.useResponsiveThemeTokens;
|
|
606
607
|
}
|
|
607
608
|
});
|
|
609
|
+
Object.defineProperty(exports, "useResponsiveThemeTokensCallback", {
|
|
610
|
+
enumerable: true,
|
|
611
|
+
get: function () {
|
|
612
|
+
return _ThemeProvider.useResponsiveThemeTokensCallback;
|
|
613
|
+
}
|
|
614
|
+
});
|
|
608
615
|
Object.defineProperty(exports, "useSetTheme", {
|
|
609
616
|
enumerable: true,
|
|
610
617
|
get: function () {
|
|
@@ -10,8 +10,15 @@ Object.defineProperty(exports, "createMediaQueryStyles", {
|
|
|
10
10
|
return _createMediaQueryStyles.default;
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
|
+
Object.defineProperty(exports, "useAllViewportTokens", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () {
|
|
16
|
+
return _useAllViewportTokens.default;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
13
19
|
var _createStylesheet = _interopRequireDefault(require("./create-stylesheet"));
|
|
14
20
|
var _createMediaQueryStyles = _interopRequireDefault(require("./utils/create-media-query-styles"));
|
|
21
|
+
var _useAllViewportTokens = _interopRequireDefault(require("./utils/use-all-viewport-tokens"));
|
|
15
22
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
23
|
const StyleSheet = exports.StyleSheet = {
|
|
17
24
|
create: _createStylesheet.default
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _ThemeProvider = require("../../../ThemeProvider");
|
|
8
|
+
var _ViewportProvider = require("../../../ViewportProvider");
|
|
9
|
+
/**
|
|
10
|
+
* Hook to get theme tokens for all viewports at once.
|
|
11
|
+
* This is useful for components that need to support React Native Media Queries (RNMQ).
|
|
12
|
+
*
|
|
13
|
+
* All hooks are called unconditionally to comply with React's Rules of Hooks.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} componentName - The name of the component to get tokens for
|
|
16
|
+
* @param {object|function} tokens - Custom tokens or token function
|
|
17
|
+
* @param {object} variant - Variant configuration
|
|
18
|
+
* @returns {object} Object with tokens for each viewport (xs, sm, md, lg, xl, current)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const allTokens = useAllViewportTokens('StackView', tokens, variant)
|
|
22
|
+
* // Returns: { xs: {...}, sm: {...}, md: {...}, lg: {...}, xl: {...}, current: {...} }
|
|
23
|
+
*/
|
|
24
|
+
const useAllViewportTokens = (componentName, tokens, variant) => {
|
|
25
|
+
const viewport = (0, _ViewportProvider.useViewport)();
|
|
26
|
+
const xs = (0, _ThemeProvider.useThemeTokens)(componentName, tokens, variant, {
|
|
27
|
+
viewport: 'xs'
|
|
28
|
+
});
|
|
29
|
+
const sm = (0, _ThemeProvider.useThemeTokens)(componentName, tokens, variant, {
|
|
30
|
+
viewport: 'sm'
|
|
31
|
+
});
|
|
32
|
+
const md = (0, _ThemeProvider.useThemeTokens)(componentName, tokens, variant, {
|
|
33
|
+
viewport: 'md'
|
|
34
|
+
});
|
|
35
|
+
const lg = (0, _ThemeProvider.useThemeTokens)(componentName, tokens, variant, {
|
|
36
|
+
viewport: 'lg'
|
|
37
|
+
});
|
|
38
|
+
const xl = (0, _ThemeProvider.useThemeTokens)(componentName, tokens, variant, {
|
|
39
|
+
viewport: 'xl'
|
|
40
|
+
});
|
|
41
|
+
const current = (0, _ThemeProvider.useThemeTokens)(componentName, tokens, variant, {
|
|
42
|
+
viewport
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
xs,
|
|
46
|
+
sm,
|
|
47
|
+
md,
|
|
48
|
+
lg,
|
|
49
|
+
xl,
|
|
50
|
+
current
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
var _default = exports.default = useAllViewportTokens;
|
package/lib/esm/Button/Button.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ButtonBase from './ButtonBase';
|
|
3
3
|
import buttonPropTypes, { textAndA11yText } from './propTypes';
|
|
4
|
-
import { useThemeTokensCallback } from '../ThemeProvider';
|
|
4
|
+
import { useThemeTokensCallback, useResponsiveThemeTokensCallback, useTheme } from '../ThemeProvider';
|
|
5
5
|
import { a11yProps } from '../utils/props';
|
|
6
6
|
import { useViewport } from '../ViewportProvider';
|
|
7
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -13,16 +13,23 @@ const Button = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
13
13
|
...props
|
|
14
14
|
} = _ref;
|
|
15
15
|
const viewport = useViewport();
|
|
16
|
-
const
|
|
16
|
+
const {
|
|
17
|
+
themeOptions: {
|
|
18
|
+
enableMediaQueryStyleSheet
|
|
19
|
+
}
|
|
20
|
+
} = useTheme();
|
|
21
|
+
const buttonVariant = enableMediaQueryStyleSheet ? variant : {
|
|
17
22
|
viewport,
|
|
18
23
|
...variant
|
|
19
24
|
};
|
|
20
|
-
const
|
|
25
|
+
const useTokens = enableMediaQueryStyleSheet ? useResponsiveThemeTokensCallback : useThemeTokensCallback;
|
|
26
|
+
const getTokens = useTokens('Button', tokens, buttonVariant);
|
|
21
27
|
return /*#__PURE__*/_jsx(ButtonBase, {
|
|
22
28
|
...props,
|
|
23
29
|
tokens: getTokens,
|
|
24
30
|
accessibilityRole: accessibilityRole,
|
|
25
|
-
ref: ref
|
|
31
|
+
ref: ref,
|
|
32
|
+
viewport: viewport
|
|
26
33
|
});
|
|
27
34
|
});
|
|
28
35
|
Button.displayName = 'Button';
|