@telus-uds/components-base 3.5.2 → 3.6.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 CHANGED
@@ -1,12 +1,27 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Tue, 08 Apr 2025 19:33:55 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 24 Apr 2025 18:52:13 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.6.0
8
+
9
+ Thu, 24 Apr 2025 18:52:13 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `MultiSelectFilter`: add new tokens (sergio.ramirez@telus.com)
14
+ - `Box`: add RNMQ support (guillermo.peitzner@telus.com)
15
+ - Bump @telus-uds/system-theme-tokens to v4.4.0
16
+
17
+ ### Patches
18
+
19
+ - `ExpandCollapseMini`: allow support for style variants (Mauricio.BatresMontejo@telus.com)
20
+ - Update react dependencies to match valid versions (sergio.ramirez@telus.com)
21
+
7
22
  ## 3.5.2
8
23
 
9
- Tue, 08 Apr 2025 19:33:55 GMT
24
+ Tue, 08 Apr 2025 19:36:14 GMT
10
25
 
11
26
  ### Patches
12
27
 
@@ -15,6 +15,7 @@ var _Image = _interopRequireDefault(require("react-native-web/dist/cjs/exports/I
15
15
  var _ThemeProvider = require("../ThemeProvider");
16
16
  var _utils = require("../utils");
17
17
  var _backgroundImageStylesMap = _interopRequireDefault(require("./backgroundImageStylesMap"));
18
+ var _ViewportProvider = require("../ViewportProvider");
18
19
  var _jsxRuntime = require("react/jsx-runtime");
19
20
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
20
21
  const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
@@ -203,8 +204,19 @@ const Box = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
203
204
  ...(0, _utils.getA11yPropsFromHtmlTag)(tag, accessibilityRole),
204
205
  ...selectProps(rest)
205
206
  };
206
- const themeTokens = (0, _ThemeProvider.useThemeTokens)('Box', tokens, variant);
207
- const styles = {
207
+ const viewport = (0, _ViewportProvider.useViewport)();
208
+ const {
209
+ themeOptions
210
+ } = (0, _ThemeProvider.useTheme)();
211
+ const {
212
+ enableMediaQueryStyleSheet
213
+ } = themeOptions;
214
+ const useTokens = enableMediaQueryStyleSheet ? _ThemeProvider.useResponsiveThemeTokens : _ThemeProvider.useThemeTokens;
215
+ const themeTokens = useTokens('Box', tokens, variant, !enableMediaQueryStyleSheet && {
216
+ viewport
217
+ });
218
+ const getSpacingTokens = (0, _ThemeProvider.useThemeTokensCallback)('spacingScale');
219
+ let boxStyles = {
208
220
  flex,
209
221
  paddingLeft: (0, _utils.useSpacingScale)(left),
210
222
  paddingRight: (0, _utils.useSpacingScale)(right),
@@ -212,8 +224,38 @@ const Box = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
212
224
  paddingBottom: (0, _utils.useSpacingScale)(bottom),
213
225
  ...selectBoxStyles(themeTokens, customGradient)
214
226
  };
227
+ let boxMediaIds;
228
+ if (enableMediaQueryStyleSheet) {
229
+ const {
230
+ transformedThemeTokens
231
+ } = Object.entries(themeTokens).reduce((acc, _ref4) => {
232
+ let [vp] = _ref4;
233
+ acc.transformedThemeTokens[vp] = {
234
+ paddingLeft: (0, _utils.getSpacingScale)(left, vp, getSpacingTokens),
235
+ paddingRight: (0, _utils.getSpacingScale)(right, vp, getSpacingTokens),
236
+ paddingTop: (0, _utils.getSpacingScale)(top, vp, getSpacingTokens),
237
+ paddingBottom: (0, _utils.getSpacingScale)(bottom, vp, getSpacingTokens)
238
+ };
239
+ return acc;
240
+ }, {
241
+ transformedThemeTokens: {}
242
+ });
243
+ const mediaQueryStyles = (0, _utils.createMediaQueryStyles)(transformedThemeTokens);
244
+ const {
245
+ ids
246
+ } = _utils.StyleSheet.create({
247
+ box: {
248
+ ...mediaQueryStyles
249
+ }
250
+ });
251
+ boxStyles = {
252
+ flex,
253
+ ...selectBoxStyles(themeTokens[viewport], customGradient)
254
+ };
255
+ boxMediaIds = ids.box;
256
+ }
215
257
  let content = children;
216
- if (typeof customGradient === 'function') content = customGradient(styles.colors, styles)(children);
258
+ if (typeof customGradient === 'function') content = customGradient(boxStyles.colors, boxStyles)(children);
217
259
  const {
218
260
  src = '',
219
261
  alt = '',
@@ -247,23 +289,27 @@ const Box = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
247
289
  });
248
290
  }
249
291
  }, [backgroundImage, backgroundImageWidth, backgroundImageHeight, src]);
292
+ const dataSetValue = boxMediaIds ? {
293
+ media: boxMediaIds,
294
+ ...dataSet
295
+ } : dataSet;
250
296
  if (scroll) {
251
297
  const scrollProps = typeof scroll === 'object' ? scroll : {};
252
- scrollProps.contentContainerStyle = [styles, scrollProps.contentContainerStyle];
298
+ scrollProps.contentContainerStyle = [boxStyles, scrollProps.contentContainerStyle];
253
299
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScrollView.default, {
254
300
  ...scrollProps,
255
301
  ...props,
256
302
  testID: testID,
257
- dataSet: dataSet,
303
+ dataSet: dataSetValue,
258
304
  ref: ref,
259
305
  children: content
260
306
  });
261
307
  }
262
308
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
263
309
  ...props,
264
- style: styles,
310
+ style: boxStyles,
265
311
  testID: testID,
266
- dataSet: dataSet,
312
+ dataSet: dataSetValue,
267
313
  ref: ref,
268
314
  children: content
269
315
  });
@@ -8,6 +8,7 @@ var _react = _interopRequireDefault(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _ExpandCollapse = _interopRequireDefault(require("../ExpandCollapse"));
10
10
  var _utils = require("../utils");
11
+ var _props = require("../utils/props");
11
12
  var _ExpandCollapseMiniControl = _interopRequireDefault(require("./ExpandCollapseMiniControl"));
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -85,6 +86,10 @@ ExpandCollapseMini.propTypes = {
85
86
  * Optional variant object to override the default theme tokens
86
87
  */
87
88
  tokens: (0, _utils.getTokensPropType)('ExpandCollapseMini'),
89
+ /**
90
+ * ExpandCollapseMini variant.
91
+ */
92
+ variant: _props.variantProp.propType,
88
93
  /**
89
94
  * The dataSet prop allows to pass data-* attributes element to the component.
90
95
  */
@@ -23,21 +23,7 @@ const presentationOnly = {
23
23
  // Stop RNW from stopping clicks from bubbling to Control
24
24
  focusable: false // Stop RNW from setting tabIndex={0}: focus goes to Control only
25
25
  };
26
- const selectLinkTokens = _ref => {
27
- let {
28
- color,
29
- textLine,
30
- lineHeight,
31
- fontSize
32
- } = _ref;
33
- return {
34
- color,
35
- textLine,
36
- blockLineHeight: lineHeight,
37
- blockFontSize: fontSize
38
- };
39
- };
40
- const ExpandCollapseMiniControl = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
26
+ const ExpandCollapseMiniControl = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
41
27
  let {
42
28
  pressableState,
43
29
  collapseTitle,
@@ -46,22 +32,28 @@ const ExpandCollapseMiniControl = /*#__PURE__*/_react.default.forwardRef((_ref2,
46
32
  tokens,
47
33
  variant = {},
48
34
  ...rest
49
- } = _ref2;
35
+ } = _ref;
50
36
  const {
51
37
  expanded,
52
38
  hover,
53
- focus
39
+ focus,
40
+ pressed
54
41
  } = pressableState || {};
55
- // we only want focus outline when focusing, if user is pressing we don't want the border.
56
42
  const {
57
- outerBorderColor
58
- } = (0, _ThemeProvider.useThemeTokens)('Link', {}, {}, {
59
- focus: _Platform.default.OS !== 'web' ? expanded : focus
43
+ quiet
44
+ } = variant;
45
+ const isFocusVisible = _Platform.default.OS === 'web' ? focus && !pressed && !hover : expanded;
46
+ const linkTokens = (0, _ThemeProvider.useThemeTokens)('Link', {}, {
47
+ ...variant,
48
+ quiet: expanded ?? quiet
49
+ }, {
50
+ focus: isFocusVisible,
51
+ hover,
52
+ pressed
60
53
  });
61
54
  const {
62
55
  size,
63
- icon,
64
- ...themeTokens
56
+ icon
65
57
  } = (0, _ThemeProvider.useThemeTokens)('ExpandCollapseMiniControl', tokens, variant, {
66
58
  expanded,
67
59
  focus
@@ -95,9 +87,8 @@ const ExpandCollapseMiniControl = /*#__PURE__*/_react.default.forwardRef((_ref2,
95
87
  icon: icon,
96
88
  iconPosition: iconPosition,
97
89
  tokens: linkState => ({
98
- ...getTokens(linkState),
99
- ...selectLinkTokens(themeTokens),
100
- outerBorderColor
90
+ ...linkTokens,
91
+ ...getTokens(linkState)
101
92
  }),
102
93
  ref: ref,
103
94
  ...presentationOnly,
@@ -137,6 +137,10 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
137
137
  buttonIconPadding,
138
138
  subtitleColor,
139
139
  dividerColor,
140
+ iconColor,
141
+ buttonBackgroundColor,
142
+ iconColorSelected,
143
+ buttonBackgroundColorSelected,
140
144
  ...restTokens
141
145
  } = (0, _ThemeProvider.useThemeTokens)('MultiSelectFilter', tokens, {
142
146
  ...variant,
@@ -159,7 +163,9 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
159
163
  paddingBottom: labelPaddingBottom,
160
164
  paddingLeft: labelPaddingLeft,
161
165
  paddingRight: labelPaddingRight,
162
- iconBackground: buttonIconBackgroundColor
166
+ iconBackground: buttonIconBackgroundColor,
167
+ iconColor: isSelected ? iconColorSelected : iconColor,
168
+ backgroundColor: isSelected ? buttonBackgroundColorSelected : buttonBackgroundColor
163
169
  };
164
170
  const getButtonDropdownTokens = (0, _ThemeProvider.useThemeTokensCallback)('ButtonDropdown', dropdownTokens, variant);
165
171
  const getButtonTokens = buttonState => (0, _utils.selectTokens)('ButtonDropdown', getButtonDropdownTokens(buttonState));
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _useResponsiveProp = require("./useResponsiveProp");
8
+ /**
9
+ * Resolves spacing options from the provided space object.
10
+ *
11
+ * @param {Object} space - The space configuration object.
12
+ * @param {Object} [space.options] - The options for spacing.
13
+ * @param {number|string} [space.options.size] - The size of the spacing. Can be a number or a string.
14
+ * @param {string} [space.options.variant] - The variant of the spacing.
15
+ * @param {number} [space.options.subtract=0] - A value to subtract from the spacing size.
16
+ * @returns {Object} An object containing resolved spacing tokens, variant, overridden flag, and subtract value.
17
+ * @property {Object} tokens - The resolved spacing tokens.
18
+ * @property {number|string} tokens.size - The size of the spacing.
19
+ * @property {string} [variant] - The variant of the spacing.
20
+ * @property {boolean} overridden - Indicates if the size is explicitly overridden as a number.
21
+ * @property {number} subtract - The value to subtract from the spacing size.
22
+ */
23
+ const resolveSpacingOptions = space => {
24
+ if (!space?.options) return {};
25
+ const {
26
+ size,
27
+ variant,
28
+ subtract = 0
29
+ } = space.options;
30
+ const overridden = typeof size === 'number';
31
+ return {
32
+ tokens: {
33
+ size
34
+ },
35
+ variant,
36
+ overridden,
37
+ subtract
38
+ };
39
+ };
40
+
41
+ /**
42
+ * Calculates the spacing scale based on the provided space value, viewport, and spacing tokens.
43
+ *
44
+ * @param {Object} spaceValue - The space value configuration, which may include responsive properties.
45
+ * @param {Object} viewport - The current viewport dimensions or configuration.
46
+ * @param {Function} getSpacingTokens - A function that retrieves spacing tokens based on the provided options.
47
+ * @returns {number} The calculated spacing scale, ensuring it is non-negative.
48
+ */
49
+ const getSpacingScale = (spaceValue, viewport, getSpacingTokens) => {
50
+ const {
51
+ tokens,
52
+ variant,
53
+ overridden,
54
+ subtract = 0
55
+ } = resolveSpacingOptions(spaceValue);
56
+ const space = !overridden && (spaceValue?.space ?? (0, _useResponsiveProp.resolveResponsiveProp)(spaceValue, viewport, 0));
57
+ const {
58
+ size
59
+ } = getSpacingTokens({
60
+ ...variant,
61
+ space: typeof space === 'number' ? space : 0,
62
+ viewport
63
+ }, tokens);
64
+ return Math.max(size - subtract, 0);
65
+ };
66
+ var _default = exports.default = getSpacingScale;
@@ -19,7 +19,8 @@ var _exportNames = {
19
19
  htmlAttrs: true,
20
20
  transformGradient: true,
21
21
  convertFromMegaByteToByte: true,
22
- formatImageSource: true
22
+ formatImageSource: true,
23
+ getSpacingScale: true
23
24
  };
24
25
  Object.defineProperty(exports, "BaseView", {
25
26
  enumerable: true,
@@ -45,6 +46,12 @@ Object.defineProperty(exports, "formatImageSource", {
45
46
  return _formatImageSource.default;
46
47
  }
47
48
  });
49
+ Object.defineProperty(exports, "getSpacingScale", {
50
+ enumerable: true,
51
+ get: function () {
52
+ return _getSpacingScale.default;
53
+ }
54
+ });
48
55
  Object.defineProperty(exports, "htmlAttrs", {
49
56
  enumerable: true,
50
57
  get: function () {
@@ -240,6 +247,7 @@ var _htmlAttrs = _interopRequireDefault(require("./htmlAttrs"));
240
247
  var _transformGradient = require("./transformGradient");
241
248
  var _convertFromMegaByteToByte = _interopRequireDefault(require("./convertFromMegaByteToByte"));
242
249
  var _formatImageSource = _interopRequireDefault(require("./formatImageSource"));
250
+ var _getSpacingScale = _interopRequireDefault(require("./getSpacingScale"));
243
251
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
244
252
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
245
253
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -6,9 +6,10 @@ import Platform from "react-native-web/dist/exports/Platform";
6
6
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
7
7
  import ImageBackground from "react-native-web/dist/exports/ImageBackground";
8
8
  import Image from "react-native-web/dist/exports/Image";
9
- import { useThemeTokens } from '../ThemeProvider';
10
- import { a11yProps, getA11yPropsFromHtmlTag, getTokensPropType, layoutTags, responsiveProps, selectSystemProps, spacingProps, useResponsiveProp, useSpacingScale, variantProp, viewProps } from '../utils';
9
+ import { useTheme, useThemeTokens, useResponsiveThemeTokens, useThemeTokensCallback } from '../ThemeProvider';
10
+ import { a11yProps, createMediaQueryStyles, getA11yPropsFromHtmlTag, getTokensPropType, layoutTags, responsiveProps, selectSystemProps, spacingProps, useResponsiveProp, useSpacingScale, variantProp, viewProps, StyleSheet as RNMQStyleSheet, getSpacingScale } from '../utils';
11
11
  import backgroundImageStylesMap from './backgroundImageStylesMap';
12
+ import { useViewport } from '../ViewportProvider';
12
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
14
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
14
15
 
@@ -196,8 +197,19 @@ const Box = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
196
197
  ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
197
198
  ...selectProps(rest)
198
199
  };
199
- const themeTokens = useThemeTokens('Box', tokens, variant);
200
- const styles = {
200
+ const viewport = useViewport();
201
+ const {
202
+ themeOptions
203
+ } = useTheme();
204
+ const {
205
+ enableMediaQueryStyleSheet
206
+ } = themeOptions;
207
+ const useTokens = enableMediaQueryStyleSheet ? useResponsiveThemeTokens : useThemeTokens;
208
+ const themeTokens = useTokens('Box', tokens, variant, !enableMediaQueryStyleSheet && {
209
+ viewport
210
+ });
211
+ const getSpacingTokens = useThemeTokensCallback('spacingScale');
212
+ let boxStyles = {
201
213
  flex,
202
214
  paddingLeft: useSpacingScale(left),
203
215
  paddingRight: useSpacingScale(right),
@@ -205,8 +217,38 @@ const Box = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
205
217
  paddingBottom: useSpacingScale(bottom),
206
218
  ...selectBoxStyles(themeTokens, customGradient)
207
219
  };
220
+ let boxMediaIds;
221
+ if (enableMediaQueryStyleSheet) {
222
+ const {
223
+ transformedThemeTokens
224
+ } = Object.entries(themeTokens).reduce((acc, _ref4) => {
225
+ let [vp] = _ref4;
226
+ acc.transformedThemeTokens[vp] = {
227
+ paddingLeft: getSpacingScale(left, vp, getSpacingTokens),
228
+ paddingRight: getSpacingScale(right, vp, getSpacingTokens),
229
+ paddingTop: getSpacingScale(top, vp, getSpacingTokens),
230
+ paddingBottom: getSpacingScale(bottom, vp, getSpacingTokens)
231
+ };
232
+ return acc;
233
+ }, {
234
+ transformedThemeTokens: {}
235
+ });
236
+ const mediaQueryStyles = createMediaQueryStyles(transformedThemeTokens);
237
+ const {
238
+ ids
239
+ } = RNMQStyleSheet.create({
240
+ box: {
241
+ ...mediaQueryStyles
242
+ }
243
+ });
244
+ boxStyles = {
245
+ flex,
246
+ ...selectBoxStyles(themeTokens[viewport], customGradient)
247
+ };
248
+ boxMediaIds = ids.box;
249
+ }
208
250
  let content = children;
209
- if (typeof customGradient === 'function') content = customGradient(styles.colors, styles)(children);
251
+ if (typeof customGradient === 'function') content = customGradient(boxStyles.colors, boxStyles)(children);
210
252
  const {
211
253
  src = '',
212
254
  alt = '',
@@ -240,23 +282,27 @@ const Box = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
240
282
  });
241
283
  }
242
284
  }, [backgroundImage, backgroundImageWidth, backgroundImageHeight, src]);
285
+ const dataSetValue = boxMediaIds ? {
286
+ media: boxMediaIds,
287
+ ...dataSet
288
+ } : dataSet;
243
289
  if (scroll) {
244
290
  const scrollProps = typeof scroll === 'object' ? scroll : {};
245
- scrollProps.contentContainerStyle = [styles, scrollProps.contentContainerStyle];
291
+ scrollProps.contentContainerStyle = [boxStyles, scrollProps.contentContainerStyle];
246
292
  return /*#__PURE__*/_jsx(ScrollView, {
247
293
  ...scrollProps,
248
294
  ...props,
249
295
  testID: testID,
250
- dataSet: dataSet,
296
+ dataSet: dataSetValue,
251
297
  ref: ref,
252
298
  children: content
253
299
  });
254
300
  }
255
301
  return /*#__PURE__*/_jsx(View, {
256
302
  ...props,
257
- style: styles,
303
+ style: boxStyles,
258
304
  testID: testID,
259
- dataSet: dataSet,
305
+ dataSet: dataSetValue,
260
306
  ref: ref,
261
307
  children: content
262
308
  });
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import ExpandCollapse from '../ExpandCollapse';
4
4
  import { getTokensPropType, selectSystemProps, contentfulProps } from '../utils';
5
+ import { variantProp } from '../utils/props';
5
6
  import ExpandCollapseMiniControl from './ExpandCollapseMiniControl';
6
7
  import { jsx as _jsx } from "react/jsx-runtime";
7
8
  const [selectContainerProps, selectedContainerPropTypes] = selectSystemProps([contentfulProps]);
@@ -78,6 +79,10 @@ ExpandCollapseMini.propTypes = {
78
79
  * Optional variant object to override the default theme tokens
79
80
  */
80
81
  tokens: getTokensPropType('ExpandCollapseMini'),
82
+ /**
83
+ * ExpandCollapseMini variant.
84
+ */
85
+ variant: variantProp.propType,
81
86
  /**
82
87
  * The dataSet prop allows to pass data-* attributes element to the component.
83
88
  */
@@ -16,21 +16,7 @@ const presentationOnly = {
16
16
  // Stop RNW from stopping clicks from bubbling to Control
17
17
  focusable: false // Stop RNW from setting tabIndex={0}: focus goes to Control only
18
18
  };
19
- const selectLinkTokens = _ref => {
20
- let {
21
- color,
22
- textLine,
23
- lineHeight,
24
- fontSize
25
- } = _ref;
26
- return {
27
- color,
28
- textLine,
29
- blockLineHeight: lineHeight,
30
- blockFontSize: fontSize
31
- };
32
- };
33
- const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
19
+ const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
34
20
  let {
35
21
  pressableState,
36
22
  collapseTitle,
@@ -39,22 +25,28 @@ const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref2, ref) =>
39
25
  tokens,
40
26
  variant = {},
41
27
  ...rest
42
- } = _ref2;
28
+ } = _ref;
43
29
  const {
44
30
  expanded,
45
31
  hover,
46
- focus
32
+ focus,
33
+ pressed
47
34
  } = pressableState || {};
48
- // we only want focus outline when focusing, if user is pressing we don't want the border.
49
35
  const {
50
- outerBorderColor
51
- } = useThemeTokens('Link', {}, {}, {
52
- focus: Platform.OS !== 'web' ? expanded : focus
36
+ quiet
37
+ } = variant;
38
+ const isFocusVisible = Platform.OS === 'web' ? focus && !pressed && !hover : expanded;
39
+ const linkTokens = useThemeTokens('Link', {}, {
40
+ ...variant,
41
+ quiet: expanded ?? quiet
42
+ }, {
43
+ focus: isFocusVisible,
44
+ hover,
45
+ pressed
53
46
  });
54
47
  const {
55
48
  size,
56
- icon,
57
- ...themeTokens
49
+ icon
58
50
  } = useThemeTokens('ExpandCollapseMiniControl', tokens, variant, {
59
51
  expanded,
60
52
  focus
@@ -88,9 +80,8 @@ const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref2, ref) =>
88
80
  icon: icon,
89
81
  iconPosition: iconPosition,
90
82
  tokens: linkState => ({
91
- ...getTokens(linkState),
92
- ...selectLinkTokens(themeTokens),
93
- outerBorderColor
83
+ ...linkTokens,
84
+ ...getTokens(linkState)
94
85
  }),
95
86
  ref: ref,
96
87
  ...presentationOnly,
@@ -130,6 +130,10 @@ const MultiSelectFilter = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
130
130
  buttonIconPadding,
131
131
  subtitleColor,
132
132
  dividerColor,
133
+ iconColor,
134
+ buttonBackgroundColor,
135
+ iconColorSelected,
136
+ buttonBackgroundColorSelected,
133
137
  ...restTokens
134
138
  } = useThemeTokens('MultiSelectFilter', tokens, {
135
139
  ...variant,
@@ -152,7 +156,9 @@ const MultiSelectFilter = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
152
156
  paddingBottom: labelPaddingBottom,
153
157
  paddingLeft: labelPaddingLeft,
154
158
  paddingRight: labelPaddingRight,
155
- iconBackground: buttonIconBackgroundColor
159
+ iconBackground: buttonIconBackgroundColor,
160
+ iconColor: isSelected ? iconColorSelected : iconColor,
161
+ backgroundColor: isSelected ? buttonBackgroundColorSelected : buttonBackgroundColor
156
162
  };
157
163
  const getButtonDropdownTokens = useThemeTokensCallback('ButtonDropdown', dropdownTokens, variant);
158
164
  const getButtonTokens = buttonState => selectTokens('ButtonDropdown', getButtonDropdownTokens(buttonState));
@@ -0,0 +1,61 @@
1
+ import { resolveResponsiveProp } from './useResponsiveProp';
2
+
3
+ /**
4
+ * Resolves spacing options from the provided space object.
5
+ *
6
+ * @param {Object} space - The space configuration object.
7
+ * @param {Object} [space.options] - The options for spacing.
8
+ * @param {number|string} [space.options.size] - The size of the spacing. Can be a number or a string.
9
+ * @param {string} [space.options.variant] - The variant of the spacing.
10
+ * @param {number} [space.options.subtract=0] - A value to subtract from the spacing size.
11
+ * @returns {Object} An object containing resolved spacing tokens, variant, overridden flag, and subtract value.
12
+ * @property {Object} tokens - The resolved spacing tokens.
13
+ * @property {number|string} tokens.size - The size of the spacing.
14
+ * @property {string} [variant] - The variant of the spacing.
15
+ * @property {boolean} overridden - Indicates if the size is explicitly overridden as a number.
16
+ * @property {number} subtract - The value to subtract from the spacing size.
17
+ */
18
+ const resolveSpacingOptions = space => {
19
+ if (!space?.options) return {};
20
+ const {
21
+ size,
22
+ variant,
23
+ subtract = 0
24
+ } = space.options;
25
+ const overridden = typeof size === 'number';
26
+ return {
27
+ tokens: {
28
+ size
29
+ },
30
+ variant,
31
+ overridden,
32
+ subtract
33
+ };
34
+ };
35
+
36
+ /**
37
+ * Calculates the spacing scale based on the provided space value, viewport, and spacing tokens.
38
+ *
39
+ * @param {Object} spaceValue - The space value configuration, which may include responsive properties.
40
+ * @param {Object} viewport - The current viewport dimensions or configuration.
41
+ * @param {Function} getSpacingTokens - A function that retrieves spacing tokens based on the provided options.
42
+ * @returns {number} The calculated spacing scale, ensuring it is non-negative.
43
+ */
44
+ const getSpacingScale = (spaceValue, viewport, getSpacingTokens) => {
45
+ const {
46
+ tokens,
47
+ variant,
48
+ overridden,
49
+ subtract = 0
50
+ } = resolveSpacingOptions(spaceValue);
51
+ const space = !overridden && (spaceValue?.space ?? resolveResponsiveProp(spaceValue, viewport, 0));
52
+ const {
53
+ size
54
+ } = getSpacingTokens({
55
+ ...variant,
56
+ space: typeof space === 'number' ? space : 0,
57
+ viewport
58
+ }, tokens);
59
+ return Math.max(size - subtract, 0);
60
+ };
61
+ export default getSpacingScale;
@@ -22,4 +22,5 @@ export { default as BaseView } from './BaseView';
22
22
  export { default as htmlAttrs } from './htmlAttrs';
23
23
  export { transformGradient } from './transformGradient';
24
24
  export { default as convertFromMegaByteToByte } from './convertFromMegaByteToByte';
25
- export { default as formatImageSource } from './formatImageSource';
25
+ export { default as formatImageSource } from './formatImageSource';
26
+ export { default as getSpacingScale } from './getSpacingScale';
package/lib/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "@gorhom/portal": "^1.0.14",
13
13
  "@react-native-picker/picker": "^2.9.0",
14
14
  "@telus-uds/system-constants": "^3.0.0",
15
- "@telus-uds/system-theme-tokens": "^4.3.0",
15
+ "@telus-uds/system-theme-tokens": "^4.4.0",
16
16
  "airbnb-prop-types": "^2.16.0",
17
17
  "css-mediaquery": "^0.1.2",
18
18
  "expo-document-picker": "^13.0.1",
@@ -56,8 +56,8 @@
56
56
  "module": "lib/esm/index.js",
57
57
  "name": "@telus-uds/components-base",
58
58
  "peerDependencies": {
59
- "react": "^18.2.0",
60
- "react-dom": "^18.2.0",
59
+ "react": ">=18.2.0 <19.0.0",
60
+ "react-dom": ">=18.2.0 <19.0.0",
61
61
  "react-native": "^0.74.5",
62
62
  "react-native-web": "^0.19.10",
63
63
  "react-native-svg": "15.7.1"
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.5.2",
87
+ "version": "3.6.0",
88
88
  "types": "types/index.d.ts"
89
89
  }
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "@gorhom/portal": "^1.0.14",
13
13
  "@react-native-picker/picker": "^2.9.0",
14
14
  "@telus-uds/system-constants": "^3.0.0",
15
- "@telus-uds/system-theme-tokens": "^4.3.0",
15
+ "@telus-uds/system-theme-tokens": "^4.4.0",
16
16
  "airbnb-prop-types": "^2.16.0",
17
17
  "css-mediaquery": "^0.1.2",
18
18
  "expo-document-picker": "^13.0.1",
@@ -56,8 +56,8 @@
56
56
  "module": "lib/esm/index.js",
57
57
  "name": "@telus-uds/components-base",
58
58
  "peerDependencies": {
59
- "react": "^18.2.0",
60
- "react-dom": "^18.2.0",
59
+ "react": ">=18.2.0 <19.0.0",
60
+ "react-dom": ">=18.2.0 <19.0.0",
61
61
  "react-native": "^0.74.5",
62
62
  "react-native-web": "^0.19.10",
63
63
  "react-native-svg": "15.7.1"
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.5.2",
87
+ "version": "3.6.0",
88
88
  "types": "types/index.d.ts"
89
89
  }
package/src/Box/Box.jsx CHANGED
@@ -1,9 +1,15 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { View, ScrollView, Platform, StyleSheet, ImageBackground, Image } from 'react-native'
4
- import { useThemeTokens } from '../ThemeProvider'
4
+ import {
5
+ useTheme,
6
+ useThemeTokens,
7
+ useResponsiveThemeTokens,
8
+ useThemeTokensCallback
9
+ } from '../ThemeProvider'
5
10
  import {
6
11
  a11yProps,
12
+ createMediaQueryStyles,
7
13
  getA11yPropsFromHtmlTag,
8
14
  getTokensPropType,
9
15
  layoutTags,
@@ -13,9 +19,12 @@ import {
13
19
  useResponsiveProp,
14
20
  useSpacingScale,
15
21
  variantProp,
16
- viewProps
22
+ viewProps,
23
+ StyleSheet as RNMQStyleSheet,
24
+ getSpacingScale
17
25
  } from '../utils'
18
26
  import backgroundImageStylesMap from './backgroundImageStylesMap'
27
+ import { useViewport } from '../ViewportProvider'
19
28
 
20
29
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
21
30
 
@@ -212,8 +221,20 @@ const Box = React.forwardRef(
212
221
  ...selectProps(rest)
213
222
  }
214
223
 
215
- const themeTokens = useThemeTokens('Box', tokens, variant)
216
- const styles = {
224
+ const viewport = useViewport()
225
+ const { themeOptions } = useTheme()
226
+ const { enableMediaQueryStyleSheet } = themeOptions
227
+
228
+ const useTokens = enableMediaQueryStyleSheet ? useResponsiveThemeTokens : useThemeTokens
229
+ const themeTokens = useTokens(
230
+ 'Box',
231
+ tokens,
232
+ variant,
233
+ !enableMediaQueryStyleSheet && { viewport }
234
+ )
235
+ const getSpacingTokens = useThemeTokensCallback('spacingScale')
236
+
237
+ let boxStyles = {
217
238
  flex,
218
239
  paddingLeft: useSpacingScale(left),
219
240
  paddingRight: useSpacingScale(right),
@@ -221,10 +242,40 @@ const Box = React.forwardRef(
221
242
  paddingBottom: useSpacingScale(bottom),
222
243
  ...selectBoxStyles(themeTokens, customGradient)
223
244
  }
245
+ let boxMediaIds
246
+
247
+ if (enableMediaQueryStyleSheet) {
248
+ const { transformedThemeTokens } = Object.entries(themeTokens).reduce(
249
+ (acc, [vp]) => {
250
+ acc.transformedThemeTokens[vp] = {
251
+ paddingLeft: getSpacingScale(left, vp, getSpacingTokens),
252
+ paddingRight: getSpacingScale(right, vp, getSpacingTokens),
253
+ paddingTop: getSpacingScale(top, vp, getSpacingTokens),
254
+ paddingBottom: getSpacingScale(bottom, vp, getSpacingTokens)
255
+ }
256
+ return acc
257
+ },
258
+ {
259
+ transformedThemeTokens: {}
260
+ }
261
+ )
262
+
263
+ const mediaQueryStyles = createMediaQueryStyles(transformedThemeTokens)
264
+ const { ids } = RNMQStyleSheet.create({
265
+ box: {
266
+ ...mediaQueryStyles
267
+ }
268
+ })
269
+ boxStyles = {
270
+ flex,
271
+ ...selectBoxStyles(themeTokens[viewport], customGradient)
272
+ }
273
+ boxMediaIds = ids.box
274
+ }
224
275
 
225
276
  let content = children
226
277
  if (typeof customGradient === 'function')
227
- content = customGradient(styles.colors, styles)(children)
278
+ content = customGradient(boxStyles.colors, boxStyles)(children)
228
279
 
229
280
  const { src = '', alt = '', resizeMode = '', position = '', align = '' } = backgroundImage || {}
230
281
  const backgroundImageResizeMode = useResponsiveProp(resizeMode, 'cover')
@@ -256,17 +307,19 @@ const Box = React.forwardRef(
256
307
  }
257
308
  }, [backgroundImage, backgroundImageWidth, backgroundImageHeight, src])
258
309
 
310
+ const dataSetValue = boxMediaIds ? { media: boxMediaIds, ...dataSet } : dataSet
311
+
259
312
  if (scroll) {
260
313
  const scrollProps = typeof scroll === 'object' ? scroll : {}
261
- scrollProps.contentContainerStyle = [styles, scrollProps.contentContainerStyle]
314
+ scrollProps.contentContainerStyle = [boxStyles, scrollProps.contentContainerStyle]
262
315
  return (
263
- <ScrollView {...scrollProps} {...props} testID={testID} dataSet={dataSet} ref={ref}>
316
+ <ScrollView {...scrollProps} {...props} testID={testID} dataSet={dataSetValue} ref={ref}>
264
317
  {content}
265
318
  </ScrollView>
266
319
  )
267
320
  }
268
321
  return (
269
- <View {...props} style={styles} testID={testID} dataSet={dataSet} ref={ref}>
322
+ <View {...props} style={boxStyles} testID={testID} dataSet={dataSetValue} ref={ref}>
270
323
  {content}
271
324
  </View>
272
325
  )
@@ -2,6 +2,7 @@ import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import ExpandCollapse from '../ExpandCollapse'
4
4
  import { getTokensPropType, selectSystemProps, contentfulProps } from '../utils'
5
+ import { variantProp } from '../utils/props'
5
6
  import ExpandCollapseMiniControl from './ExpandCollapseMiniControl'
6
7
 
7
8
  const [selectContainerProps, selectedContainerPropTypes] = selectSystemProps([contentfulProps])
@@ -79,6 +80,10 @@ ExpandCollapseMini.propTypes = {
79
80
  * Optional variant object to override the default theme tokens
80
81
  */
81
82
  tokens: getTokensPropType('ExpandCollapseMini'),
83
+ /**
84
+ * ExpandCollapseMini variant.
85
+ */
86
+ variant: variantProp.propType,
82
87
  /**
83
88
  * The dataSet prop allows to pass data-* attributes element to the component.
84
89
  */
@@ -15,13 +15,6 @@ const presentationOnly = {
15
15
  focusable: false // Stop RNW from setting tabIndex={0}: focus goes to Control only
16
16
  }
17
17
 
18
- const selectLinkTokens = ({ color, textLine, lineHeight, fontSize }) => ({
19
- color,
20
- textLine,
21
- blockLineHeight: lineHeight,
22
- blockFontSize: fontSize
23
- })
24
-
25
18
  const ExpandCollapseMiniControl = React.forwardRef(
26
19
  (
27
20
  {
@@ -35,20 +28,24 @@ const ExpandCollapseMiniControl = React.forwardRef(
35
28
  },
36
29
  ref
37
30
  ) => {
38
- const { expanded, hover, focus } = pressableState || {}
39
- // we only want focus outline when focusing, if user is pressing we don't want the border.
40
- const { outerBorderColor } = useThemeTokens(
31
+ const { expanded, hover, focus, pressed } = pressableState || {}
32
+ const { quiet } = variant
33
+ const isFocusVisible = Platform.OS === 'web' ? focus && !pressed && !hover : expanded
34
+
35
+ const linkTokens = useThemeTokens(
41
36
  'Link',
42
37
  {},
43
- {},
44
- { focus: Platform.OS !== 'web' ? expanded : focus }
45
- )
46
- const { size, icon, ...themeTokens } = useThemeTokens(
47
- 'ExpandCollapseMiniControl',
48
- tokens,
49
- variant,
50
- { expanded, focus }
38
+ { ...variant, quiet: expanded ?? quiet },
39
+ {
40
+ focus: isFocusVisible,
41
+ hover,
42
+ pressed
43
+ }
51
44
  )
45
+ const { size, icon } = useThemeTokens('ExpandCollapseMiniControl', tokens, variant, {
46
+ expanded,
47
+ focus
48
+ })
52
49
 
53
50
  // Choose hover styles when any part of Control is hoverred
54
51
  const appearance = { ...variant, hover }
@@ -75,9 +72,8 @@ const ExpandCollapseMiniControl = React.forwardRef(
75
72
  icon={icon}
76
73
  iconPosition={iconPosition}
77
74
  tokens={(linkState) => ({
78
- ...getTokens(linkState),
79
- ...selectLinkTokens(themeTokens),
80
- outerBorderColor
75
+ ...linkTokens,
76
+ ...getTokens(linkState)
81
77
  })}
82
78
  ref={ref}
83
79
  {...presentationOnly}
@@ -134,6 +134,10 @@ const MultiSelectFilter = React.forwardRef(
134
134
  buttonIconPadding,
135
135
  subtitleColor,
136
136
  dividerColor,
137
+ iconColor,
138
+ buttonBackgroundColor,
139
+ iconColorSelected,
140
+ buttonBackgroundColorSelected,
137
141
  ...restTokens
138
142
  } = useThemeTokens(
139
143
  'MultiSelectFilter',
@@ -154,7 +158,9 @@ const MultiSelectFilter = React.forwardRef(
154
158
  paddingBottom: labelPaddingBottom,
155
159
  paddingLeft: labelPaddingLeft,
156
160
  paddingRight: labelPaddingRight,
157
- iconBackground: buttonIconBackgroundColor
161
+ iconBackground: buttonIconBackgroundColor,
162
+ iconColor: isSelected ? iconColorSelected : iconColor,
163
+ backgroundColor: isSelected ? buttonBackgroundColorSelected : buttonBackgroundColor
158
164
  }
159
165
  const getButtonDropdownTokens = useThemeTokensCallback(
160
166
  'ButtonDropdown',
@@ -0,0 +1,50 @@
1
+ import { resolveResponsiveProp } from './useResponsiveProp'
2
+
3
+ /**
4
+ * Resolves spacing options from the provided space object.
5
+ *
6
+ * @param {Object} space - The space configuration object.
7
+ * @param {Object} [space.options] - The options for spacing.
8
+ * @param {number|string} [space.options.size] - The size of the spacing. Can be a number or a string.
9
+ * @param {string} [space.options.variant] - The variant of the spacing.
10
+ * @param {number} [space.options.subtract=0] - A value to subtract from the spacing size.
11
+ * @returns {Object} An object containing resolved spacing tokens, variant, overridden flag, and subtract value.
12
+ * @property {Object} tokens - The resolved spacing tokens.
13
+ * @property {number|string} tokens.size - The size of the spacing.
14
+ * @property {string} [variant] - The variant of the spacing.
15
+ * @property {boolean} overridden - Indicates if the size is explicitly overridden as a number.
16
+ * @property {number} subtract - The value to subtract from the spacing size.
17
+ */
18
+ const resolveSpacingOptions = (space) => {
19
+ if (!space?.options) return {}
20
+
21
+ const { size, variant, subtract = 0 } = space.options
22
+ const overridden = typeof size === 'number'
23
+
24
+ return { tokens: { size }, variant, overridden, subtract }
25
+ }
26
+
27
+ /**
28
+ * Calculates the spacing scale based on the provided space value, viewport, and spacing tokens.
29
+ *
30
+ * @param {Object} spaceValue - The space value configuration, which may include responsive properties.
31
+ * @param {Object} viewport - The current viewport dimensions or configuration.
32
+ * @param {Function} getSpacingTokens - A function that retrieves spacing tokens based on the provided options.
33
+ * @returns {number} The calculated spacing scale, ensuring it is non-negative.
34
+ */
35
+ const getSpacingScale = (spaceValue, viewport, getSpacingTokens) => {
36
+ const { tokens, variant, overridden, subtract = 0 } = resolveSpacingOptions(spaceValue)
37
+ const space = !overridden && (spaceValue?.space ?? resolveResponsiveProp(spaceValue, viewport, 0))
38
+
39
+ const { size } = getSpacingTokens(
40
+ {
41
+ ...variant,
42
+ space: typeof space === 'number' ? space : 0,
43
+ viewport
44
+ },
45
+ tokens
46
+ )
47
+ return Math.max(size - subtract, 0)
48
+ }
49
+
50
+ export default getSpacingScale
@@ -23,3 +23,4 @@ export { default as htmlAttrs } from './htmlAttrs'
23
23
  export { transformGradient } from './transformGradient'
24
24
  export { default as convertFromMegaByteToByte } from './convertFromMegaByteToByte'
25
25
  export { default as formatImageSource } from './formatImageSource'
26
+ export { default as getSpacingScale } from './getSpacingScale'