@telus-uds/components-base 3.8.0 → 3.10.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,17 +1,41 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Fri, 23 May 2025 15:12:18 GMT and should not be manually modified.
3
+ This log was last generated on Tue, 24 Jun 2025 18:53:53 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.10.0
8
+
9
+ Tue, 24 Jun 2025 18:53:53 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `ButtonGroup`: equalWidth variant added (35577399+JoshHC@users.noreply.github.com)
14
+ - Bump @telus-uds/system-theme-tokens to v4.8.0
15
+
16
+ ## 3.9.0
17
+
18
+ Tue, 10 Jun 2025 20:25:05 GMT
19
+
20
+ ### Minor changes
21
+
22
+ - `ToggleSwitch`: update UI for mobile devices (guillermo.peitzner@telus.com)
23
+ - `MultiSelectFilter`: preservation of original case (uppercase/lowercase) for label when using custom dictionary prop enabled" (35577399+JoshHC@users.noreply.github.com)
24
+ - Bump @telus-uds/system-theme-tokens to v4.7.0
25
+
26
+ ### Patches
27
+
28
+ - `MultiSelectFilter`: add containerBorderColor token (sergio.ramirez@telus.com)
29
+ - `Validator`: concatenation and 6-digit limit bugs fixed (35577399+JoshHC@users.noreply.github.com)
30
+
7
31
  ## 3.8.0
8
32
 
9
- Fri, 23 May 2025 15:12:18 GMT
33
+ Fri, 23 May 2025 15:15:58 GMT
10
34
 
11
35
  ### Minor changes
12
36
 
13
37
  - `ActivityIndicator`: new `Spinner` functionalities added because it will be deprecated soon (35577399+JoshHC@users.noreply.github.com)
14
- - `MultiSelectFilter`: close the overlay box when we click outside (sergio.ramirez@telus.com)
38
+ - `MultiSelectFilter`: close the overlay box when we click outside (sergio.ramirez@telus.com)
15
39
  - `Notification`: feature variant added for allium, koodo and pm (35577399+JoshHC@users.noreply.github.com)
16
40
  - Bump @telus-uds/system-theme-tokens to v4.6.0
17
41
 
@@ -408,7 +408,10 @@ const dictionaryContentShape = _propTypes.default.shape({
408
408
  Autocomplete.propTypes = {
409
409
  ...selectedSystemPropTypes,
410
410
  /**
411
- * Can be used to provide a function that renders a custom input:
411
+ * Can be used to provide a function that renders a custom input.
412
+ *
413
+ * @example
414
+ * ```jsx
412
415
  * <Autocomplete items={items} value={currentValue}>
413
416
  * {({ inputId, inputRef, onChange, onKeyPress, readOnly, tokens, value }) => (
414
417
  * <Search
@@ -422,6 +425,7 @@ Autocomplete.propTypes = {
422
425
  * />
423
426
  * )}
424
427
  * </Autocomplete>
428
+ * ```
425
429
  */
426
430
  children: _propTypes.default.func,
427
431
  tokens: (0, _utils.getTokensPropType)('Autocomplete'),
@@ -24,7 +24,23 @@ const getOuterBorderOffset = _ref => {
24
24
  } = _ref;
25
25
  return outerBorderGap + outerBorderWidth;
26
26
  };
27
- const selectOuterContainerStyles = _ref2 => {
27
+ const selectFlexAndWidthStyles = _ref2 => {
28
+ let {
29
+ width,
30
+ flex
31
+ } = _ref2;
32
+ const styles = {};
33
+ if (width !== undefined && width !== null) {
34
+ styles.width = width;
35
+ }
36
+ if (width === '100%') {
37
+ styles.flex = 1;
38
+ } else if (flex !== undefined && flex !== null) {
39
+ styles.flex = flex;
40
+ }
41
+ return styles;
42
+ };
43
+ const selectOuterContainerStyles = _ref3 => {
28
44
  let {
29
45
  opacity,
30
46
  outerBorderColor,
@@ -32,7 +48,7 @@ const selectOuterContainerStyles = _ref2 => {
32
48
  outerBorderGap,
33
49
  borderRadius,
34
50
  outerBackgroundColor
35
- } = _ref2;
51
+ } = _ref3;
36
52
  return {
37
53
  ..._Platform.default.select({
38
54
  native: {
@@ -49,13 +65,13 @@ const selectOuterContainerStyles = _ref2 => {
49
65
  })
50
66
  };
51
67
  };
52
- const selectOuterSizeStyles = _ref3 => {
68
+ const selectOuterSizeStyles = _ref4 => {
53
69
  let {
54
70
  outerBorderGap,
55
71
  outerBorderWidth,
56
72
  width,
57
73
  height
58
- } = _ref3;
74
+ } = _ref4;
59
75
  // The inner container's bounding box is the bounding box of the button overall
60
76
  // so this many device pixels will sit outside of the overall bounding box
61
77
  const outerBorderOffset = getOuterBorderOffset({
@@ -100,7 +116,7 @@ const selectOuterSizeStyles = _ref3 => {
100
116
  sizeStyles.height = height;
101
117
  return sizeStyles;
102
118
  };
103
- const selectInnerContainerStyles = _ref4 => {
119
+ const selectInnerContainerStyles = _ref5 => {
104
120
  let {
105
121
  backgroundColor,
106
122
  paddingLeft,
@@ -114,14 +130,14 @@ const selectInnerContainerStyles = _ref4 => {
114
130
  borderTopWidth,
115
131
  borderBottomWidth,
116
132
  minWidth
117
- } = _ref4;
133
+ } = _ref5;
118
134
  // Subtract border width from padding so overall button width/height doesn't
119
135
  // jump around if the border width changes (avoiding NaN and negative padding)
120
- const offsetBorder = _ref5 => {
136
+ const offsetBorder = _ref6 => {
121
137
  let {
122
138
  value,
123
139
  borderSize = borderWidth
124
- } = _ref5;
140
+ } = _ref6;
125
141
  return typeof value === 'number' && typeof borderSize === 'number' ? Math.max(0, value - borderSize) : value;
126
142
  };
127
143
  return {
@@ -146,7 +162,7 @@ const selectInnerContainerStyles = _ref4 => {
146
162
  ...(0, _ThemeProvider.applyShadowToken)(shadow)
147
163
  };
148
164
  };
149
- const selectBorderStyles = _ref6 => {
165
+ const selectBorderStyles = _ref7 => {
150
166
  let {
151
167
  borderColor,
152
168
  borderWidth,
@@ -155,7 +171,7 @@ const selectBorderStyles = _ref6 => {
155
171
  borderRightWidth,
156
172
  borderTopWidth,
157
173
  borderBottomWidth
158
- } = _ref6;
174
+ } = _ref7;
159
175
  return {
160
176
  borderColor,
161
177
  borderWidth,
@@ -166,7 +182,7 @@ const selectBorderStyles = _ref6 => {
166
182
  borderBottomWidth
167
183
  };
168
184
  };
169
- const selectTextStyles = (_ref7, themeOptions) => {
185
+ const selectTextStyles = (_ref8, themeOptions) => {
170
186
  let {
171
187
  fontSize,
172
188
  color,
@@ -176,7 +192,7 @@ const selectTextStyles = (_ref7, themeOptions) => {
176
192
  textAlign,
177
193
  textLine,
178
194
  textLineStyle
179
- } = _ref7;
195
+ } = _ref8;
180
196
  return (0, _ThemeProvider.applyTextStyles)({
181
197
  fontSize,
182
198
  color,
@@ -189,10 +205,10 @@ const selectTextStyles = (_ref7, themeOptions) => {
189
205
  textDecorationStyle: textLineStyle
190
206
  });
191
207
  };
192
- const selectWebOnlyStyles = (inactive, themeTokens, _ref8) => {
208
+ const selectWebOnlyStyles = (inactive, themeTokens, _ref9) => {
193
209
  let {
194
210
  accessibilityRole
195
- } = _ref8;
211
+ } = _ref9;
196
212
  return _Platform.default.select({
197
213
  web: {
198
214
  // if it would overflow the container, wraps instead
@@ -205,27 +221,27 @@ const selectWebOnlyStyles = (inactive, themeTokens, _ref8) => {
205
221
  default: {}
206
222
  });
207
223
  };
208
- const selectButtonStyles = _ref9 => {
224
+ const selectButtonStyles = _ref10 => {
209
225
  let {
210
226
  textAlign
211
- } = _ref9;
227
+ } = _ref10;
212
228
  return {
213
229
  flexDirection: 'row',
214
230
  justifyContent: textAlign
215
231
  };
216
232
  };
217
- const selectItemIconTokens = _ref10 => {
233
+ const selectItemIconTokens = _ref11 => {
218
234
  let {
219
235
  color,
220
236
  iconColor,
221
237
  iconSize
222
- } = _ref10;
238
+ } = _ref11;
223
239
  return {
224
240
  size: iconSize,
225
241
  color: iconColor || color
226
242
  };
227
243
  };
228
- const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref11, ref) => {
244
+ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref12, ref) => {
229
245
  let {
230
246
  id,
231
247
  href,
@@ -240,7 +256,7 @@ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref11, ref) => {
240
256
  iconPosition = icon ? 'left' : undefined,
241
257
  iconProps,
242
258
  ...rawRest
243
- } = _ref11;
259
+ } = _ref12;
244
260
  const {
245
261
  onPress,
246
262
  ...rest
@@ -254,7 +270,9 @@ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref11, ref) => {
254
270
  const systemProps = selectProps(rest);
255
271
  const getPressableStyle = pressableState => {
256
272
  const themeTokens = resolveButtonTokens(pressableState);
257
- return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens), selectOuterSizeStyles(themeTokens)];
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
+ const flexAndWidthStyles = themeTokens.width === '100%' && themeTokens.flex === 1 ? selectFlexAndWidthStyles(themeTokens) : {};
275
+ return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens), ...(Object.keys(flexAndWidthStyles).length > 0 ? [flexAndWidthStyles] : []), selectOuterSizeStyles(themeTokens)];
258
276
  };
259
277
  const {
260
278
  themeOptions
@@ -19,6 +19,15 @@ var _jsxRuntime = require("react/jsx-runtime");
19
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
20
20
  const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
21
21
  const [selectItemProps, selectedItemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.focusHandlerProps, _utils.pressProps, _utils.viewProps]);
22
+ const getStackWrapTokens = variant => {
23
+ return _Platform.default.select({
24
+ web: {
25
+ justifyContent: variant?.width === 'equal' ? 'space-evenly' : 'flex-start',
26
+ width: variant?.width === 'equal' ? '100%' : 'auto'
27
+ },
28
+ default: {}
29
+ });
30
+ };
22
31
  const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
23
32
  let {
24
33
  variant,
@@ -51,7 +60,12 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
51
60
  const themeTokens = (0, _ThemeProvider.useThemeTokens)('ButtonGroup', tokens, variant, {
52
61
  viewport
53
62
  });
54
- const stackTokens = (0, _utils.selectTokens)('StackView', themeTokens);
63
+ const themeStackTokens = (0, _utils.selectTokens)('StackView', themeTokens);
64
+ const variantStackTokens = getStackWrapTokens(variant);
65
+ const stackTokens = {
66
+ ...themeStackTokens,
67
+ ...variantStackTokens
68
+ };
55
69
  const {
56
70
  direction,
57
71
  space,
@@ -61,7 +75,15 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
61
75
  padding,
62
76
  gap
63
77
  } = themeTokens;
64
- const getButtonTokens = (0, _ThemeProvider.useThemeTokensCallback)('ButtonGroupItem', tokens, variant);
78
+ const themeButtonTokensCallback = (0, _ThemeProvider.useThemeTokensCallback)('ButtonGroupItem', tokens, variant);
79
+ const getButtonTokens = state => {
80
+ const themeButtonTokens = themeButtonTokensCallback(state);
81
+ return {
82
+ ...themeButtonTokens,
83
+ width: variant?.width === 'equal' ? '100%' : 'auto',
84
+ flex: variant?.width === 'equal' ? 1 : undefined
85
+ };
86
+ };
65
87
  const {
66
88
  currentValues,
67
89
  toggleOneValue
@@ -104,7 +126,7 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
104
126
  padding,
105
127
  ...(_Platform.default.OS === 'web' ? {
106
128
  gap,
107
- width: 'fit-content'
129
+ width: variant?.width === 'equal' ? '100%' : 'fit-content'
108
130
  } : {
109
131
  alignSelf: 'flex-start'
110
132
  })
@@ -63,6 +63,7 @@ const staticStyles = _StyleSheet.default.create({
63
63
  });
64
64
  const selectContainerStyle = (enableFullscreen, themeTokens) => ({
65
65
  borderColor: themeTokens.borderColor,
66
+ backgroundColor: themeTokens.backgroundColor,
66
67
  ..._Platform.default.select({
67
68
  web: {
68
69
  position: enableFullscreen ? 'fixed' : 'absolute'
@@ -114,7 +115,8 @@ const ModalOverlay = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
114
115
  maxHeight: maxHeightSize
115
116
  };
116
117
  const {
117
- closeIcon: CloseIconComponent
118
+ closeIcon: CloseIconComponent,
119
+ backgroundColor
118
120
  } = themeTokens;
119
121
  const getCopy = (0, _utils.useCopy)({
120
122
  dictionary: _dictionary.default,
@@ -127,7 +129,10 @@ const ModalOverlay = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
127
129
  onLayout: onLayout,
128
130
  style: [overlaidPosition, containerWidthHeight, staticStyles.positioner, !isReady && staticStyles.hidden, selectContainerStyle(enableFullscreen, themeTokens)],
129
131
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Card.default, {
130
- tokens: staticStyles.card,
132
+ tokens: {
133
+ ...staticStyles.card,
134
+ backgroundColor
135
+ },
131
136
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
132
137
  style: [staticStyles.closeButtonContainer, selectCloseButtonContainerStyles(themeTokens)],
133
138
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
@@ -142,6 +142,7 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
142
142
  buttonBackgroundColor,
143
143
  iconColorSelected,
144
144
  buttonBackgroundColorSelected,
145
+ containerBorderColor,
145
146
  ...restTokens
146
147
  } = (0, _ThemeProvider.useThemeTokens)('MultiSelectFilter', tokens, {
147
148
  ...variant,
@@ -287,7 +288,7 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
287
288
  ...headerStyles,
288
289
  lineHeight: headerLineHeight
289
290
  },
290
- children: getCopy('filterByLabel').replace(/%\{filterCategory\}/g, label.toLowerCase())
291
+ children: getCopy('filterByLabel').replace(/%\{filterCategory\}/g, label)
291
292
  })
292
293
  })
293
294
  }), subtitle && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
@@ -308,6 +309,7 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
308
309
  style: styles.options,
309
310
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScrollView.default, {
310
311
  onLayout: handleScrollViewLayout,
312
+ style: styles.scrollContainer,
311
313
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
312
314
  distribute: "between",
313
315
  onLayout: handleRowLayout,
@@ -326,12 +328,11 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
326
328
  })]
327
329
  });
328
330
  const controlsContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
329
- children: [isScrolling ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
331
+ children: [isScrolling && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
330
332
  tokens: {
331
333
  color: dividerColor
332
- },
333
- space: 4
334
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Spacer.default, {
334
+ }
335
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Spacer.default, {
335
336
  space: 4
336
337
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
337
338
  style: selectControlsTokens(restTokens),
@@ -388,7 +389,8 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
388
389
  minWidth: windowWidth,
389
390
  tokens: {
390
391
  ...tokens,
391
- maxWidth: true
392
+ maxWidth: true,
393
+ borderColor: containerBorderColor
392
394
  },
393
395
  copy: copy,
394
396
  isReady: isReady,
@@ -414,7 +416,8 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
414
416
  minWidth: minWidth,
415
417
  tokens: {
416
418
  ...tokens,
417
- maxWidth: items.length > MAX_ITEMS_THRESHOLD ? true : maxWidth
419
+ maxWidth: items.length > MAX_ITEMS_THRESHOLD ? true : maxWidth,
420
+ borderColor: containerBorderColor
418
421
  },
419
422
  copy: copy,
420
423
  isReady: isReady,
@@ -442,6 +445,9 @@ const styles = _StyleSheet.default.create({
442
445
  },
443
446
  options: {
444
447
  flex: 1
448
+ },
449
+ scrollContainer: {
450
+ padding: 1
445
451
  }
446
452
  });
447
453
 
@@ -101,6 +101,17 @@ const selectSwitchStyles = _ref6 => {
101
101
  })
102
102
  };
103
103
  };
104
+ const selectMobileTokens = tokens => ({
105
+ ..._Platform.default.select({
106
+ web: {},
107
+ default: {
108
+ switchSize: tokens?.mobileSwitchSize,
109
+ trackHeight: tokens?.mobileTrackHeight,
110
+ width: tokens?.mobileWidth,
111
+ trackBorderWidth: tokens?.mobileTrackBorderWidth
112
+ }
113
+ })
114
+ });
104
115
  const selectLabelStyles = _ref7 => {
105
116
  let {
106
117
  labelMarginLeft
@@ -153,7 +164,7 @@ const ToggleSwitch = /*#__PURE__*/_react.default.forwardRef((_ref9, ref) => {
153
164
  onChange
154
165
  });
155
166
  const handlePress = event => setValue(!currentValue, event);
156
- const getButtonTokens = buttonState => selectButtonTokens(getTokens(buttonState), getTokens(themeTokens));
167
+ const getButtonTokens = buttonState => selectButtonTokens(getTokens(buttonState, selectMobileTokens(themeTokens)), getTokens(themeTokens, selectMobileTokens(themeTokens)));
157
168
  const uniqueId = (0, _utils.useUniqueId)('toggleSwitch');
158
169
  const inputId = id ?? uniqueId;
159
170
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_StackView.default, {
@@ -186,7 +197,7 @@ const ToggleSwitch = /*#__PURE__*/_react.default.forwardRef((_ref9, ref) => {
186
197
  onPress: handlePress,
187
198
  ...selectProps(rest),
188
199
  children: buttonState => {
189
- const stateTokens = getTokens(buttonState);
200
+ const stateTokens = getTokens(buttonState, selectMobileTokens(themeTokens));
190
201
  const IconComponent = stateTokens.icon;
191
202
  const switchStyles = selectSwitchStyles(stateTokens);
192
203
  const trackStyles = selectTrackStyles(stateTokens);