@telus-uds/components-base 3.19.0 → 3.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/lib/cjs/Button/ButtonDropdown.js +1 -0
  3. package/lib/cjs/ExpandCollapseMini/ExpandCollapseMiniControl.js +8 -21
  4. package/lib/cjs/Link/LinkBase.js +8 -9
  5. package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +8 -8
  6. package/lib/cjs/Responsive/ResponsiveWithMediaQueryStyleSheet.js +1 -1
  7. package/lib/cjs/Spacer/Spacer.js +65 -5
  8. package/lib/cjs/StackView/StackView.js +62 -12
  9. package/lib/cjs/Tabs/TabsDropdown.js +4 -5
  10. package/lib/cjs/utils/index.js +8 -0
  11. package/lib/cjs/utils/ssr-media-query/index.js +7 -0
  12. package/lib/cjs/utils/ssr-media-query/utils/use-all-viewport-tokens.js +53 -0
  13. package/lib/cjs/utils/useMediaQuerySpacing.js +121 -0
  14. package/lib/esm/Button/ButtonDropdown.js +1 -0
  15. package/lib/esm/ExpandCollapseMini/ExpandCollapseMiniControl.js +8 -21
  16. package/lib/esm/Link/LinkBase.js +8 -9
  17. package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +8 -8
  18. package/lib/esm/Responsive/ResponsiveWithMediaQueryStyleSheet.js +1 -1
  19. package/lib/esm/Spacer/Spacer.js +66 -6
  20. package/lib/esm/StackView/StackView.js +63 -13
  21. package/lib/esm/Tabs/TabsDropdown.js +4 -5
  22. package/lib/esm/utils/index.js +1 -0
  23. package/lib/esm/utils/ssr-media-query/index.js +2 -1
  24. package/lib/esm/utils/ssr-media-query/utils/use-all-viewport-tokens.js +48 -0
  25. package/lib/esm/utils/useMediaQuerySpacing.js +116 -0
  26. package/lib/package.json +5 -5
  27. package/package.json +5 -5
  28. package/src/Button/ButtonDropdown.jsx +1 -0
  29. package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +9 -16
  30. package/src/Link/LinkBase.jsx +11 -9
  31. package/src/MultiSelectFilter/MultiSelectFilter.jsx +9 -8
  32. package/src/Responsive/ResponsiveWithMediaQueryStyleSheet.jsx +1 -1
  33. package/src/Spacer/Spacer.jsx +54 -7
  34. package/src/StackView/StackView.jsx +62 -9
  35. package/src/Tabs/TabsDropdown.jsx +10 -9
  36. package/src/utils/index.js +1 -0
  37. package/src/utils/ssr-media-query/index.js +2 -1
  38. package/src/utils/ssr-media-query/utils/use-all-viewport-tokens.js +32 -0
  39. package/src/utils/useMediaQuerySpacing.js +124 -0
package/CHANGELOG.md CHANGED
@@ -1,9 +1,37 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Fri, 03 Oct 2025 20:34:06 GMT and should not be manually modified.
3
+ This log was last generated on Tue, 21 Oct 2025 14:46:26 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.21.0
8
+
9
+ Tue, 21 Oct 2025 14:46:26 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `StackView`: add RNMQ support (guillermo.peitzner@telus.com)
14
+
15
+ ### Patches
16
+
17
+ - `Responsive`: fix console warning (guillermo.peitzner@telus.com)
18
+ - `TabsDropdown`: outline unnecessary property removed (35577399+JoshHC@users.noreply.github.com)
19
+
20
+ ## 3.20.0
21
+
22
+ Fri, 10 Oct 2025 15:11:05 GMT
23
+
24
+ ### Minor changes
25
+
26
+ - `Spacer`: add RNMQ support (guillermo.peitzner@telus.com)
27
+ - Bump @telus-uds/system-theme-tokens to v4.15.1
28
+
29
+ ### Patches
30
+
31
+ - `ButtonDropdown`: Small size variant updates. (oscar.palencia@telus.com)
32
+ - `MultiSelectfilter`: rowLimit prop issue causing display problems fixed (35577399+JoshHC@users.noreply.github.com)
33
+ - `ExpandCollapseMini`: extra padding removed (35577399+JoshHC@users.noreply.github.com)
34
+
7
35
  ## 3.19.0
8
36
 
9
37
  Fri, 03 Oct 2025 20:34:06 GMT
@@ -64,6 +64,7 @@ const selectDescriptionTextStyles = tokens => ({
64
64
  fontName: tokens?.descriptionFontName,
65
65
  fontSize: tokens?.descriptionFontSize,
66
66
  fontWeight: tokens?.descriptionFontWeight,
67
+ lineHeight: tokens?.descriptionLineHeight,
67
68
  fontColor: tokens?.color
68
69
  }),
69
70
  paddingBottom: tokens?.descriptionTextPaddingBottom
@@ -73,35 +73,21 @@ const ExpandCollapseMiniControl = /*#__PURE__*/_react.default.forwardRef((_ref,
73
73
  const isHovered = hover || linkHover;
74
74
  const iconBaselineOffset = 0;
75
75
  const hoverTranslateY = 4;
76
-
77
- // Calculate baseline alignment to vertically center icon with text
78
- // This combines font and icon metrics with adjustments for visual balance
79
- const fontBaseline = fontSize / hoverTranslateY; // Quarter of font size - adjusts for text's visual center point
80
- const iconBaseline = iconSize / hoverTranslateY; // Quarter of icon size - adjusts for icon's visual center point
81
- const staticOffset = hoverTranslateY; // Fixed downward adjustment to fine-tune vertical alignment
82
- const sizeCompensation = -Math.abs(iconSize - fontSize); // Compensates when icon and text sizes differ significantly
83
-
76
+ const fontBaseline = fontSize / hoverTranslateY;
77
+ const iconBaseline = iconSize / hoverTranslateY;
78
+ const staticOffset = hoverTranslateY;
79
+ const sizeCompensation = -Math.abs(iconSize - fontSize);
84
80
  const baselineAlignment = fontBaseline + iconBaseline - staticOffset + sizeCompensation;
85
- if (_Platform.default.OS !== 'web') {
86
- // For native platforms, use baseline alignment with optional offset
87
- return {
88
- iconTranslateY: baselineAlignment + iconBaselineOffset
89
- };
90
- }
81
+ const mobileAdjustment = _Platform.default.OS !== 'web' ? -2 : 0;
91
82
  if (isHovered) {
92
- // Apply animation offset to the baseline-aligned position
93
- // When expanded: move icon UP (1.3 the hover distance for clear movement)
94
- // When collapsed: move icon DOWN (single hover distance)
95
83
  const hoverMovementDistance = 1.3;
96
84
  const animationOffset = expanded ? -(hoverTranslateY * hoverMovementDistance) : hoverTranslateY;
97
85
  return {
98
- iconTranslateY: baselineAlignment + iconBaselineOffset + animationOffset
86
+ iconTranslateY: baselineAlignment + iconBaselineOffset + animationOffset + mobileAdjustment
99
87
  };
100
88
  }
101
-
102
- // Default state uses baseline alignment with optional offset
103
89
  return {
104
- iconTranslateY: baselineAlignment + iconBaselineOffset
90
+ iconTranslateY: baselineAlignment + iconBaselineOffset + mobileAdjustment
105
91
  };
106
92
  };
107
93
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Link.Link, {
@@ -112,6 +98,7 @@ const ExpandCollapseMiniControl = /*#__PURE__*/_react.default.forwardRef((_ref,
112
98
  ...linkTokens,
113
99
  ...getTokens(linkState),
114
100
  iconSize,
101
+ blockFontSize: fontSize,
115
102
  blockLineHeight: lineHeight
116
103
  }),
117
104
  ref: ref,
@@ -187,7 +187,8 @@ const LinkBase = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
187
187
  const themeTokens = resolveLinkTokens(linkState);
188
188
  const outerBorderStyles = selectOuterBorderStyles(themeTokens);
189
189
  const decorationStyles = selectDecorationStyles(themeTokens);
190
- return [outerBorderStyles, staticStyles.outerBorderStyles, blockLeftStyle, decorationStyles, hasIcon && staticStyles.rowContainer];
190
+ const mobileCompensation = null;
191
+ return [outerBorderStyles, mobileCompensation, blockLeftStyle, decorationStyles, hasIcon && staticStyles.rowContainer];
191
192
  },
192
193
  children: linkState => {
193
194
  const themeTokens = resolveLinkTokens(linkState);
@@ -200,10 +201,12 @@ const LinkBase = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
200
201
  const {
201
202
  iconSpace
202
203
  } = themeTokens;
204
+ const isTextOnlyLink = !IconComponent && !icon && accessibilityRole === 'link';
205
+ const adjustedIconSpace = _Platform.default.OS !== 'web' && isTextOnlyLink ? 0 : iconSpace;
203
206
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.IconText, {
204
207
  icon: IconComponent,
205
208
  iconPosition: iconPosition,
206
- space: iconSpace,
209
+ space: adjustedIconSpace,
207
210
  iconProps: {
208
211
  ...iconProps,
209
212
  tokens: iconTokens,
@@ -270,15 +273,11 @@ const staticStyles = _StyleSheet.default.create({
270
273
  }
271
274
  })
272
275
  },
273
- outerBorderStyles: {
276
+ outerBorderCompensation: {
274
277
  ...(_Platform.default.OS !== 'web' && {
275
- margin: 0,
276
278
  marginHorizontal: 2,
277
- padding: 0
278
- }),
279
- ...(_Platform.default.OS === 'android' && {
280
- paddingHorizontal: 2,
281
- paddingTop: 2
279
+ paddingHorizontal: _Platform.default.OS === 'android' ? 2 : 0,
280
+ paddingTop: _Platform.default.OS === 'android' ? 2 : 0
282
281
  })
283
282
  }
284
283
  });
@@ -71,7 +71,6 @@ const selectContainerStyle = (windowHeight, windowWidth) => ({
71
71
  width: windowWidth
72
72
  });
73
73
  const TOTAL_COLUMNS = 12;
74
- const MAX_ITEMS_THRESHOLD = 12;
75
74
  const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
76
75
  let {
77
76
  label,
@@ -178,12 +177,13 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
178
177
  });
179
178
  const colSizeNotMobile = items.length > rowLimit ? 2 : 1;
180
179
  const colSize = viewport !== 'xs' ? colSizeNotMobile : 1;
181
- const itemsLengthNotMobile = items.length > 24 ? items.length / 2 : rowLimit;
182
- const rowLength = viewport !== 'xs' ? itemsLengthNotMobile : items.length;
180
+ let rowLength = items.length;
181
+ if (viewport !== 'xs' && colSize === 2) {
182
+ rowLength = Math.ceil(items.length / 2);
183
+ }
183
184
  _react.default.useEffect(() => {
184
- if (colSize === 1) return setMaxWidth(false);
185
- return colSize === 2 && setMaxWidth(true);
186
- }, [colSize]);
185
+ setMaxWidth(items.length >= rowLimit);
186
+ }, [items.length, rowLimit]);
187
187
  _react.default.useEffect(() => setCheckedIds(currentValues ?? []), [currentValues]);
188
188
  const uniqueFields = ['id', 'label'];
189
189
  if (!(0, _utils.containUniqueFields)(items, uniqueFields)) {
@@ -430,14 +430,14 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
430
430
  dismissWhenPressedOutside: dismissWhenPressedOutside,
431
431
  onClose: onClose,
432
432
  overlaidPosition: overlaidPosition,
433
- maxHeight: items.length > MAX_ITEMS_THRESHOLD ? true : maxHeight,
433
+ maxHeight: items.length >= rowLimit ? true : maxHeight,
434
434
  maxHeightSize: maxHeightSize,
435
435
  maxWidthSize: maxWidthSize,
436
436
  minHeight: minHeight,
437
437
  minWidth: minWidth,
438
438
  tokens: {
439
439
  ...tokens,
440
- maxWidth: items.length > MAX_ITEMS_THRESHOLD ? true : maxWidth,
440
+ maxWidth: items.length >= rowLimit ? true : maxWidth,
441
441
  borderColor: containerBorderColor
442
442
  },
443
443
  copy: copy,
@@ -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
  };
@@ -6,9 +6,11 @@ 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 _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
10
9
  var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
10
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
11
11
  var _utils = require("../utils");
12
+ var _useMediaQuerySpacing = _interopRequireDefault(require("../utils/useMediaQuerySpacing"));
13
+ var _useTheme = _interopRequireDefault(require("../ThemeProvider/useTheme"));
12
14
  var _jsxRuntime = require("react/jsx-runtime");
13
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
16
  /**
@@ -65,13 +67,66 @@ const Spacer = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
65
67
  let {
66
68
  space = 1,
67
69
  direction = 'column',
70
+ dataSet,
68
71
  ...rest
69
72
  } = _ref;
70
- const size = (0, _utils.useSpacingScale)(space);
71
- const sizeStyle = selectSizeStyle(size, direction);
73
+ const {
74
+ themeOptions: {
75
+ enableMediaQueryStyleSheet
76
+ }
77
+ } = (0, _useTheme.default)();
78
+ const {
79
+ sizeByViewport
80
+ } = (0, _useMediaQuerySpacing.default)(space);
81
+ const fallbackSize = (0, _utils.useSpacingScale)(space);
82
+ const sizeStyle = selectSizeStyle(fallbackSize, direction);
83
+ let spacerStyles;
84
+ let dataSetValue = dataSet;
85
+ if (enableMediaQueryStyleSheet) {
86
+ const sizeKey = direction === 'row' ? 'width' : 'height';
87
+ const stylesByViewport = {
88
+ xs: {
89
+ [sizeKey]: sizeByViewport.xs,
90
+ ...staticStyles.stretch
91
+ },
92
+ sm: {
93
+ [sizeKey]: sizeByViewport.sm,
94
+ ...staticStyles.stretch
95
+ },
96
+ md: {
97
+ [sizeKey]: sizeByViewport.md,
98
+ ...staticStyles.stretch
99
+ },
100
+ lg: {
101
+ [sizeKey]: sizeByViewport.lg,
102
+ ...staticStyles.stretch
103
+ },
104
+ xl: {
105
+ [sizeKey]: sizeByViewport.xl,
106
+ ...staticStyles.stretch
107
+ }
108
+ };
109
+ const mediaQueryStyles = (0, _utils.createMediaQueryStyles)(stylesByViewport);
110
+ const {
111
+ ids,
112
+ styles
113
+ } = _utils.StyleSheet.create({
114
+ spacer: {
115
+ ...mediaQueryStyles
116
+ }
117
+ });
118
+ spacerStyles = styles.spacer;
119
+ dataSetValue = {
120
+ media: ids.spacer,
121
+ ...dataSet
122
+ };
123
+ } else {
124
+ spacerStyles = [staticStyles.stretch, sizeStyle];
125
+ }
72
126
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
73
127
  ref: ref,
74
- style: [staticStyles.stretch, sizeStyle],
128
+ style: spacerStyles,
129
+ dataSet: dataSetValue,
75
130
  ...selectProps(rest)
76
131
  });
77
132
  });
@@ -90,7 +145,12 @@ Spacer.propTypes = {
90
145
  * - `'column'` (default) applies space vertically; has a fixed height and not width.
91
146
  * - `'row'` applies space horizontally; has a fixed width and not height.
92
147
  */
93
- direction: _propTypes.default.oneOf(['column', 'row'])
148
+ direction: _propTypes.default.oneOf(['column', 'row']),
149
+ /**
150
+ * Data attributes to be applied to the element. When media query stylesheet is enabled,
151
+ * this will include media query IDs for responsive styling.
152
+ */
153
+ dataSet: _propTypes.default.object
94
154
  };
95
155
  const staticStyles = _StyleSheet.default.create({
96
156
  stretch: {
@@ -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 _ThemeProvider = require("../ThemeProvider");
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 themeTokens = (0, _ThemeProvider.useThemeTokens)('StackView', tokens, variant, {
87
- viewport
88
- });
89
- const flexStyles = (0, _common.selectFlexStyles)(themeTokens);
90
- const size = {
91
- width: themeTokens.width
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: [flexStyles, _common.staticStyles[direction], size],
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;
@@ -8,6 +8,7 @@ var _exportNames = {
8
8
  useCopy: true,
9
9
  useHash: true,
10
10
  useSpacingScale: true,
11
+ useMediaQuerySpacing: true,
11
12
  useResponsiveProp: true,
12
13
  useOverlaidPosition: true,
13
14
  useSafeLayoutEffect: true,
@@ -90,6 +91,12 @@ Object.defineProperty(exports, "useHash", {
90
91
  return _useHash.default;
91
92
  }
92
93
  });
94
+ Object.defineProperty(exports, "useMediaQuerySpacing", {
95
+ enumerable: true,
96
+ get: function () {
97
+ return _useMediaQuerySpacing.default;
98
+ }
99
+ });
93
100
  Object.defineProperty(exports, "useOverlaidPosition", {
94
101
  enumerable: true,
95
102
  get: function () {
@@ -226,6 +233,7 @@ var _info = _interopRequireDefault(require("./info"));
226
233
  var _useCopy = _interopRequireDefault(require("./useCopy"));
227
234
  var _useHash = _interopRequireDefault(require("./useHash"));
228
235
  var _useSpacingScale = _interopRequireDefault(require("./useSpacingScale"));
236
+ var _useMediaQuerySpacing = _interopRequireDefault(require("./useMediaQuerySpacing"));
229
237
  var _useResponsiveProp = _interopRequireWildcard(require("./useResponsiveProp"));
230
238
  Object.keys(_useResponsiveProp).forEach(function (key) {
231
239
  if (key === "default" || key === "__esModule") return;
@@ -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;
@@ -0,0 +1,121 @@
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 _useResponsiveProp = require("./useResponsiveProp");
9
+ /**
10
+ * @typedef {import('@telus-uds/system-constants/viewports').Viewport} Viewport
11
+ * @typedef {import('./props/spacingProps.js').SpacingValue} SpacingValue
12
+ * @typedef {import('./props/spacingProps.js').SpacingIndex} SpacingIndex
13
+ * @typedef {import('./props/spacingProps.js').SpacingObject} SpacingObject
14
+ */
15
+
16
+ /**
17
+ * A utility hook that simplifies implementing media query-based responsive spacing.
18
+ *
19
+ * This hook handles the complexity of:
20
+ * - Detecting if a space value is responsive (has viewport keys)
21
+ * - Fetching theme tokens for each viewport
22
+ * - Resolving the correct space index for each viewport
23
+ * - Extracting actual pixel values from theme tokens
24
+ *
25
+ * ## Usage
26
+ *
27
+ * ```jsx
28
+ * const { sizeByViewport } = useMediaQuerySpacing(space, 'spacingScale')
29
+ *
30
+ * // Use sizeByViewport to create media query styles
31
+ * const stylesByViewport = {
32
+ * xs: { padding: sizeByViewport.xs },
33
+ * sm: { padding: sizeByViewport.sm },
34
+ * md: { padding: sizeByViewport.md },
35
+ * lg: { padding: sizeByViewport.lg },
36
+ * xl: { padding: sizeByViewport.xl }
37
+ * }
38
+ * const mediaQueryStyles = createMediaQueryStyles(stylesByViewport)
39
+ * ```
40
+ *
41
+ * ## Parameters
42
+ *
43
+ * @param {SpacingValue} spaceValue - A spacing value (number or responsive object with viewport keys)
44
+ * @param {string} tokenKey - The theme token key to use (e.g., 'spacingScale', 'Typography')
45
+ * @param {object} [tokens={}] - Additional tokens to pass to useThemeTokens
46
+ * @param {object} [variant={}] - Variant to pass to useThemeTokens
47
+ *
48
+ * ## Returns
49
+ *
50
+ * @returns {{
51
+ * spaceIndexByViewport: { xs: number, sm: number, md: number, lg: number, xl: number },
52
+ * sizeByViewport: { xs: number, sm: number, md: number, lg: number, xl: number },
53
+ * tokensByViewport: { xs: object, sm: object, md: object, lg: object, xl: object }
54
+ * }}
55
+ *
56
+ * - `spaceIndexByViewport`: The resolved space index for each viewport
57
+ * - `sizeByViewport`: The actual pixel/number values for each viewport
58
+ * - `tokensByViewport`: The full theme tokens for each viewport (for advanced use cases)
59
+ */
60
+ const useMediaQuerySpacing = function (spaceValue) {
61
+ let tokenKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'spacingScale';
62
+ let tokens = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
63
+ let variant = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
64
+ const isResponsive = typeof spaceValue === 'object' && spaceValue !== null && !spaceValue.space && !spaceValue.options;
65
+ const getSpaceIndex = viewport => {
66
+ if (isResponsive) {
67
+ return (0, _useResponsiveProp.resolveResponsiveProp)(spaceValue, viewport);
68
+ }
69
+ if (typeof spaceValue === 'number') {
70
+ return spaceValue;
71
+ }
72
+ return spaceValue?.space ?? 1;
73
+ };
74
+ const spaceIndexByViewport = {
75
+ xs: getSpaceIndex('xs'),
76
+ sm: getSpaceIndex('sm'),
77
+ md: getSpaceIndex('md'),
78
+ lg: getSpaceIndex('lg'),
79
+ xl: getSpaceIndex('xl')
80
+ };
81
+ const tokensXs = (0, _ThemeProvider.useThemeTokens)(tokenKey, tokens, variant, {
82
+ space: spaceIndexByViewport.xs,
83
+ viewport: 'xs'
84
+ });
85
+ const tokensSm = (0, _ThemeProvider.useThemeTokens)(tokenKey, tokens, variant, {
86
+ space: spaceIndexByViewport.sm,
87
+ viewport: 'sm'
88
+ });
89
+ const tokensMd = (0, _ThemeProvider.useThemeTokens)(tokenKey, tokens, variant, {
90
+ space: spaceIndexByViewport.md,
91
+ viewport: 'md'
92
+ });
93
+ const tokensLg = (0, _ThemeProvider.useThemeTokens)(tokenKey, tokens, variant, {
94
+ space: spaceIndexByViewport.lg,
95
+ viewport: 'lg'
96
+ });
97
+ const tokensXl = (0, _ThemeProvider.useThemeTokens)(tokenKey, tokens, variant, {
98
+ space: spaceIndexByViewport.xl,
99
+ viewport: 'xl'
100
+ });
101
+ const sizeByViewport = {
102
+ xs: tokensXs.size ?? 0,
103
+ sm: tokensSm.size ?? 0,
104
+ md: tokensMd.size ?? 0,
105
+ lg: tokensLg.size ?? 0,
106
+ xl: tokensXl.size ?? 0
107
+ };
108
+ const tokensByViewport = {
109
+ xs: tokensXs,
110
+ sm: tokensSm,
111
+ md: tokensMd,
112
+ lg: tokensLg,
113
+ xl: tokensXl
114
+ };
115
+ return {
116
+ spaceIndexByViewport,
117
+ sizeByViewport,
118
+ tokensByViewport
119
+ };
120
+ };
121
+ var _default = exports.default = useMediaQuerySpacing;
@@ -55,6 +55,7 @@ const selectDescriptionTextStyles = tokens => ({
55
55
  fontName: tokens?.descriptionFontName,
56
56
  fontSize: tokens?.descriptionFontSize,
57
57
  fontWeight: tokens?.descriptionFontWeight,
58
+ lineHeight: tokens?.descriptionLineHeight,
58
59
  fontColor: tokens?.color
59
60
  }),
60
61
  paddingBottom: tokens?.descriptionTextPaddingBottom