@telus-uds/components-base 3.24.0 → 3.25.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,9 +1,22 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Fri, 12 Dec 2025 05:37:22 GMT and should not be manually modified.
3
+ This log was last generated on Mon, 12 Jan 2026 14:55:21 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.25.0
8
+
9
+ Mon, 12 Jan 2026 14:55:21 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `Status`: Added typescript support for the component (shivam.gupta3@telus.com)
14
+ - `IconButton`: Update the UI to match the design intention, add an inactive prop and selected variant (guillermo.peitzner@telus.com)
15
+ - `FlexGrid`: rename contentMinWidth prop to contentMaxWidth (guillermo.peitzner@telus.com)
16
+ - `ButtonGroup`: add item inactive prop (guillermo.peitzner@telus.com)
17
+ - `Carousel`: add contentMaxWidth prop (guillermo.peitzner@telus.com)
18
+ - Bump @telus-uds/system-theme-tokens to v4.18.0
19
+
7
20
  ## 3.24.0
8
21
 
9
22
  Fri, 12 Dec 2025 05:37:22 GMT
@@ -138,6 +138,7 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
138
138
  id = label,
139
139
  accessibilityLabel,
140
140
  ref: itemRef,
141
+ inactive: itemInactive,
141
142
  ...itemRest
142
143
  } = _ref2;
143
144
  const isSelected = currentValues.includes(id);
@@ -161,6 +162,7 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
161
162
  accessibilityLabel,
162
163
  ..._utils.a11yProps.getPositionInSet(items.length, index)
163
164
  };
165
+ const isInactive = itemInactive !== undefined ? itemInactive : inactive;
164
166
 
165
167
  // Ensure button is direct child of group as MacOS voiceover only applies "X of Y" to
166
168
  // "radio" if it's a direct child of "radiogroup", even if aria-posinset etc exists
@@ -171,7 +173,7 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
171
173
  onPress: handlePress,
172
174
  tokens: getButtonTokens,
173
175
  selected: isSelected,
174
- inactive: inactive,
176
+ inactive: isInactive,
175
177
  icon: iconProp,
176
178
  ...selectItemProps({
177
179
  ...itemRest,
@@ -225,7 +227,12 @@ ButtonGroup.propTypes = {
225
227
  /**
226
228
  * An optional ref for one individual button in the ButtonGroup
227
229
  */
228
- ref: _airbnbPropTypes.default.ref()
230
+ ref: _airbnbPropTypes.default.ref(),
231
+ /**
232
+ * If true, this individual button cannot be interacted with. Takes precedence
233
+ * over the group-level `inactive` prop. Useful for disabling specific options.
234
+ */
235
+ inactive: _propTypes.default.bool
229
236
  })),
230
237
  /**
231
238
  * If provided, this function is called when the current selection is changed
@@ -210,11 +210,18 @@ const selectRootContainerStyles = (enableHero, viewport) => {
210
210
  }
211
211
  return {};
212
212
  };
213
- const selectMainContainerStyles = (enableHero, viewport) => {
213
+ const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
214
214
  if (enableHero && viewport === 'xl' && _Platform.default.OS === 'web') {
215
215
  return {
216
216
  width: '100%',
217
- maxWidth: 1200
217
+ maxWidth: maxWidth || 1200
218
+ };
219
+ }
220
+ if (maxWidth !== null && maxWidth !== undefined) {
221
+ return {
222
+ maxWidth,
223
+ alignSelf: 'center',
224
+ width: '100%'
218
225
  };
219
226
  }
220
227
  return {};
@@ -361,11 +368,18 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
361
368
  loopDuration = transitionDuration,
362
369
  autoPlay = false,
363
370
  enablePeeking = false,
371
+ contentMaxWidth,
364
372
  ...rest
365
373
  } = _ref3;
366
374
  let childrenArray = (0, _utils.unpackFragment)(children);
367
375
  const isTransitioningRef = _react.default.useRef(false);
368
376
  const viewport = (0, _ViewportProvider.useViewport)();
377
+ const {
378
+ themeOptions
379
+ } = (0, _ThemeProvider.useTheme)();
380
+ const contentMaxWidthValue = (0, _utils.useResponsiveProp)(contentMaxWidth);
381
+ const responsiveWidth = (0, _utils.useResponsiveProp)(themeOptions?.contentMaxWidth);
382
+ const maxWidth = (0, _utils.resolveContentMaxWidth)(contentMaxWidthValue, responsiveWidth);
369
383
  const totalItems = getTotalItems(enableDisplayMultipleItemsPerSlide, childrenArray, viewport);
370
384
  const autoPlayFeatureEnabled = autoPlay && slideDuration > 0 && transitionDuration > 0 && totalItems > 1;
371
385
  // if `Carousel` only has one `Carousel.Item`, convert this to a single-item array
@@ -896,7 +910,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
896
910
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
897
911
  style: selectRootContainerStyles(enableHero, viewport),
898
912
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
899
- style: selectMainContainerStyles(enableHero, viewport),
913
+ style: selectMainContainerStyles(enableHero, viewport, maxWidth),
900
914
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_CarouselContext.CarouselProvider, {
901
915
  activeIndex: activeIndex,
902
916
  goTo: goTo,
@@ -1254,7 +1268,24 @@ Carousel.propTypes = {
1254
1268
  * If set to `true`, the Carousel will show multiple slides at once
1255
1269
  * - Default value is `false`
1256
1270
  */
1257
- enableDisplayMultipleItemsPerSlide: _propTypes.default.bool
1271
+ enableDisplayMultipleItemsPerSlide: _propTypes.default.bool,
1272
+ /**
1273
+ * The maximum width of the content in the Carousel.
1274
+ * This prop accepts responsive values for different viewports. If a number is provided,
1275
+ * it will be the max content width for the desired viewport.
1276
+ * - `xs`: 'max' | 'full' | <number>
1277
+ * - `sm`: 'max' | 'full' | <number>
1278
+ * - `md`: 'max' | 'full' | <number>
1279
+ * - `lg`: 'max' | 'full' | <number>
1280
+ * - `xl`: 'max' | 'full' | <number>
1281
+ */
1282
+ contentMaxWidth: _propTypes.default.shape({
1283
+ xl: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
1284
+ lg: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
1285
+ md: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
1286
+ sm: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
1287
+ xs: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number])
1288
+ })
1258
1289
  };
1259
1290
  Carousel.Item = _CarouselItem.default;
1260
1291
  Carousel.displayName = 'Carousel';
@@ -8,6 +8,7 @@ var _react = _interopRequireDefault(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _systemConstants = require("@telus-uds/system-constants");
10
10
  var _utils = require("../utils");
11
+ var _resolveContentMaxWidth = _interopRequireDefault(require("../utils/resolveContentMaxWidth"));
11
12
  var _Row = _interopRequireDefault(require("./Row"));
12
13
  var _Col = _interopRequireDefault(require("./Col"));
13
14
  var _GutterContext = _interopRequireDefault(require("./providers/GutterContext"));
@@ -17,47 +18,24 @@ var _ViewportProvider = require("../ViewportProvider");
17
18
  var _jsxRuntime = require("react/jsx-runtime");
18
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
20
  const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
20
- const CONTENT_MAX_WIDTH = 'max';
21
- const CONTENT_FULL_WIDTH = 'full';
22
21
 
23
22
  /**
24
- * Resolves the maximum width for content based on the provided value and responsive width.
25
- *
26
- * @param {number|string|null|undefined} contentMinWidthValue - The minimum width value for the content.
27
- * Can be a number, a special string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
28
- * @param {number} responsiveWidth - The responsive width to use when contentMinWidthValue is CONTENT_MAX_WIDTH.
29
- * @returns {number|string|null} The resolved maximum width value, or null if full width is desired.
30
- */
31
- const resolveContentMaxWidth = (contentMinWidthValue, responsiveWidth) => {
32
- if (!contentMinWidthValue || contentMinWidthValue === CONTENT_FULL_WIDTH) {
33
- return null;
34
- }
35
- if (Number.isFinite(contentMinWidthValue)) {
36
- return contentMinWidthValue;
37
- }
38
- if (contentMinWidthValue === CONTENT_MAX_WIDTH) {
39
- return responsiveWidth;
40
- }
41
- return contentMinWidthValue;
42
- };
43
-
44
- /**
45
- * Calculates the maximum width for a given viewport based on limitWidth and contentMinWidth settings.
23
+ * Calculates the maximum width for a given viewport based on limitWidth and contentMaxWidth settings.
46
24
  *
47
25
  * @param {string} viewportKey - The viewport key ('xs', 'sm', 'md', 'lg', 'xl')
48
26
  * @param {boolean} limitWidth - Whether to limit the width to viewport breakpoints
49
- * @param {any} contentMinWidth - The contentMinWidth prop value
27
+ * @param {any} contentWidthProp - The contentMaxWidth (or contentMinWidth) prop value
50
28
  * @param {number|string|null} maxWidth - The resolved max width value
51
29
  * @returns {number|string|null} The calculated maximum width for the viewport
52
30
  */
53
- const getMaxWidthForViewport = (viewportKey, limitWidth, contentMinWidth, maxWidth) => {
31
+ const getMaxWidthForViewport = (viewportKey, limitWidth, contentWidthProp, maxWidth) => {
54
32
  if (limitWidth) {
55
33
  if (viewportKey === 'xs') {
56
34
  return null;
57
35
  }
58
36
  return _systemConstants.viewports.map.get(viewportKey);
59
37
  }
60
- if (contentMinWidth) {
38
+ if (contentWidthProp) {
61
39
  return maxWidth;
62
40
  }
63
41
  return null;
@@ -81,6 +59,7 @@ const FlexGrid = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
81
59
  accessibilityRole,
82
60
  children,
83
61
  dataSet,
62
+ contentMaxWidth,
84
63
  contentMinWidth,
85
64
  ...rest
86
65
  } = _ref;
@@ -94,28 +73,31 @@ const FlexGrid = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
94
73
  } = (0, _ThemeProvider.useTheme)();
95
74
  let flexgridStyles;
96
75
  let mediaIds;
97
- const contentMinWidthValue = (0, _utils.useResponsiveProp)(contentMinWidth);
76
+
77
+ // Support both contentMaxWidth and deprecated contentMinWidth for backwards compatibility
78
+ const contentWidthProp = contentMaxWidth || contentMinWidth;
79
+ const contentWidthValue = (0, _utils.useResponsiveProp)(contentWidthProp);
98
80
  const responsiveWidth = (0, _utils.useResponsiveProp)(themeOptions?.contentMaxWidth);
99
- const maxWidth = resolveContentMaxWidth(contentMinWidthValue, responsiveWidth);
81
+ const maxWidth = (0, _resolveContentMaxWidth.default)(contentWidthValue, responsiveWidth);
100
82
  const stylesByViewport = {
101
83
  xs: {
102
- maxWidth: getMaxWidthForViewport('xs', limitWidth, contentMinWidth, maxWidth),
84
+ maxWidth: getMaxWidthForViewport('xs', limitWidth, contentWidthProp, maxWidth),
103
85
  flexDirection: reverseLevel[0] ? 'column-reverse' : 'column'
104
86
  },
105
87
  sm: {
106
- maxWidth: getMaxWidthForViewport('sm', limitWidth, contentMinWidth, maxWidth),
88
+ maxWidth: getMaxWidthForViewport('sm', limitWidth, contentWidthProp, maxWidth),
107
89
  flexDirection: reverseLevel[1] ? 'column-reverse' : 'column'
108
90
  },
109
91
  md: {
110
- maxWidth: getMaxWidthForViewport('md', limitWidth, contentMinWidth, maxWidth),
92
+ maxWidth: getMaxWidthForViewport('md', limitWidth, contentWidthProp, maxWidth),
111
93
  flexDirection: reverseLevel[2] ? 'column-reverse' : 'column'
112
94
  },
113
95
  lg: {
114
- maxWidth: getMaxWidthForViewport('lg', limitWidth, contentMinWidth, maxWidth),
96
+ maxWidth: getMaxWidthForViewport('lg', limitWidth, contentWidthProp, maxWidth),
115
97
  flexDirection: reverseLevel[3] ? 'column-reverse' : 'column'
116
98
  },
117
99
  xl: {
118
- maxWidth: getMaxWidthForViewport('xl', limitWidth, contentMinWidth, maxWidth),
100
+ maxWidth: getMaxWidthForViewport('xl', limitWidth, contentWidthProp, maxWidth),
119
101
  flexDirection: reverseLevel[4] ? 'column-reverse' : 'column'
120
102
  }
121
103
  };
@@ -211,7 +193,7 @@ FlexGrid.propTypes = {
211
193
  */
212
194
  children: _propTypes.default.node.isRequired,
213
195
  /**
214
- * The minimum width of the content in the FlexGrid.
196
+ * The maximum width of the content in the FlexGrid.
215
197
  * This prop accepts responsive values for different viewports. If a number is provided,
216
198
  * it will be the max content width for the desired viewport.
217
199
  * - `xs`: 'max' | 'full' | <number>
@@ -220,6 +202,20 @@ FlexGrid.propTypes = {
220
202
  * - `lg`: 'max' | 'full' | <number>
221
203
  * - `xl`: 'max' | 'full' | <number>
222
204
  */
205
+ contentMaxWidth: _propTypes.default.shape({
206
+ xl: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
207
+ lg: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
208
+ md: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
209
+ sm: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
210
+ xs: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number])
211
+ }),
212
+ /**
213
+ * @deprecated Use `contentMaxWidth` instead. This prop will be removed in a future version.
214
+ *
215
+ * The minimum width of the content in the FlexGrid.
216
+ * This prop accepts responsive values for different viewports. If a number is provided,
217
+ * it will be the max content width for the desired viewport.
218
+ */
223
219
  contentMinWidth: _propTypes.default.shape({
224
220
  xl: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
225
221
  lg: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
@@ -129,6 +129,7 @@ const IconButton = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
129
129
  hrefAttrs,
130
130
  testID,
131
131
  accessibilityRole = href ? 'link' : 'button',
132
+ inactive = false,
132
133
  ...rawRest
133
134
  } = _ref3;
134
135
  const {
@@ -149,8 +150,12 @@ const IconButton = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
149
150
  }
150
151
  });
151
152
  };
152
- const getTokens = (0, _ThemeProvider.useThemeTokensCallback)('IconButton', tokens, variant);
153
- const getOuterStyle = pressableState => selectOuterStyle(getTokens((0, _utils.resolvePressableState)(pressableState), variant.password));
153
+ const mergedVariant = inactive ? {
154
+ ...variant,
155
+ inactive: true
156
+ } : variant;
157
+ const getTokens = (0, _ThemeProvider.useThemeTokensCallback)('IconButton', tokens, mergedVariant);
158
+ const getOuterStyle = pressableState => selectOuterStyle(getTokens((0, _utils.resolvePressableState)(pressableState), mergedVariant.password));
154
159
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pressable.default, {
155
160
  ref: ref,
156
161
  href: href,
@@ -159,15 +164,16 @@ const IconButton = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
159
164
  style: getOuterStyle,
160
165
  ...selectedProps,
161
166
  testID: testID,
167
+ disabled: inactive,
162
168
  children: pressableState => {
163
169
  const themeTokens = getTokens((0, _utils.resolvePressableState)(pressableState));
164
170
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
165
- style: selectInnerStyle(themeTokens, variant.password),
171
+ style: selectInnerStyle(themeTokens, mergedVariant.password),
166
172
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
167
173
  icon: IconComponent || themeTokens.icon,
168
174
  title: selectedProps.accessibilityLabel,
169
175
  tokens: (0, _utils.selectTokens)('Icon', themeTokens, 'icon'),
170
- variant: variant
176
+ variant: mergedVariant
171
177
  })
172
178
  });
173
179
  }
@@ -198,7 +204,11 @@ IconButton.propTypes = {
198
204
  /**
199
205
  * Function to execute when the `Iconbutton` is pressed
200
206
  */
201
- onPress: _propTypes.default.func
207
+ onPress: _propTypes.default.func,
208
+ /**
209
+ * When true, applies the inactive variant styling
210
+ */
211
+ inactive: _propTypes.default.bool
202
212
  };
203
213
  const staticStyles = _StyleSheet.default.create({
204
214
  outer: {
@@ -332,7 +332,7 @@ const TextInputBase = /*#__PURE__*/_react.default.forwardRef((_ref8, ref) => {
332
332
  icon: ClearButtonIcon,
333
333
  onPress: handleClear,
334
334
  variant: {
335
- compact: true
335
+ subtle: true
336
336
  }
337
337
  }, "clear"));
338
338
  }
@@ -342,8 +342,7 @@ const TextInputBase = /*#__PURE__*/_react.default.forwardRef((_ref8, ref) => {
342
342
  icon: !showPassword ? passwordShowButtonIcon : passwordHideButtonIcon,
343
343
  onPress: handleShowOrHide,
344
344
  variant: {
345
- compact: true,
346
- password: true,
345
+ subtle: true,
347
346
  inactive: variant.inactive,
348
347
  size: 'large'
349
348
  },
@@ -23,7 +23,8 @@ var _exportNames = {
23
23
  formatImageSource: true,
24
24
  getSpacingScale: true,
25
25
  useVariants: true,
26
- isTouchDevice: true
26
+ isTouchDevice: true,
27
+ resolveContentMaxWidth: true
27
28
  };
28
29
  Object.defineProperty(exports, "BaseView", {
29
30
  enumerable: true,
@@ -73,6 +74,12 @@ Object.defineProperty(exports, "isTouchDevice", {
73
74
  return _isTouchDevice.default;
74
75
  }
75
76
  });
77
+ Object.defineProperty(exports, "resolveContentMaxWidth", {
78
+ enumerable: true,
79
+ get: function () {
80
+ return _resolveContentMaxWidth.default;
81
+ }
82
+ });
76
83
  Object.defineProperty(exports, "transformGradient", {
77
84
  enumerable: true,
78
85
  get: function () {
@@ -272,6 +279,7 @@ var _formatImageSource = _interopRequireDefault(require("./formatImageSource"));
272
279
  var _getSpacingScale = _interopRequireDefault(require("./getSpacingScale"));
273
280
  var _useVariants = _interopRequireDefault(require("./useVariants"));
274
281
  var _isTouchDevice = _interopRequireDefault(require("./isTouchDevice"));
282
+ var _resolveContentMaxWidth = _interopRequireDefault(require("./resolveContentMaxWidth"));
275
283
  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); }
276
284
  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; }
277
285
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ const CONTENT_MAX_WIDTH = 'max';
8
+ const CONTENT_FULL_WIDTH = 'full';
9
+
10
+ /**
11
+ * Resolves the maximum width for content based on the provided value and responsive width.
12
+ *
13
+ * @param {number|string|null|undefined} contentMaxWidthValue - The maximum width value for the content.
14
+ * Can be a number, a special string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
15
+ * @param {number} responsiveWidth - The responsive width to use when contentMaxWidthValue is CONTENT_MAX_WIDTH.
16
+ * @returns {number|string|null} The resolved maximum width value, or null if full width is desired.
17
+ */
18
+ const resolveContentMaxWidth = (contentMaxWidthValue, responsiveWidth) => {
19
+ if (!contentMaxWidthValue || contentMaxWidthValue === CONTENT_FULL_WIDTH) {
20
+ return null;
21
+ }
22
+ if (Number.isFinite(contentMaxWidthValue)) {
23
+ return contentMaxWidthValue;
24
+ }
25
+ if (contentMaxWidthValue === CONTENT_MAX_WIDTH) {
26
+ return responsiveWidth;
27
+ }
28
+ return contentMaxWidthValue;
29
+ };
30
+ var _default = exports.default = resolveContentMaxWidth;
@@ -129,6 +129,7 @@ const ButtonGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
129
129
  id = label,
130
130
  accessibilityLabel,
131
131
  ref: itemRef,
132
+ inactive: itemInactive,
132
133
  ...itemRest
133
134
  } = _ref2;
134
135
  const isSelected = currentValues.includes(id);
@@ -152,6 +153,7 @@ const ButtonGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
152
153
  accessibilityLabel,
153
154
  ...a11yProps.getPositionInSet(items.length, index)
154
155
  };
156
+ const isInactive = itemInactive !== undefined ? itemInactive : inactive;
155
157
 
156
158
  // Ensure button is direct child of group as MacOS voiceover only applies "X of Y" to
157
159
  // "radio" if it's a direct child of "radiogroup", even if aria-posinset etc exists
@@ -162,7 +164,7 @@ const ButtonGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
162
164
  onPress: handlePress,
163
165
  tokens: getButtonTokens,
164
166
  selected: isSelected,
165
- inactive: inactive,
167
+ inactive: isInactive,
166
168
  icon: iconProp,
167
169
  ...selectItemProps({
168
170
  ...itemRest,
@@ -216,7 +218,12 @@ ButtonGroup.propTypes = {
216
218
  /**
217
219
  * An optional ref for one individual button in the ButtonGroup
218
220
  */
219
- ref: ABBPropTypes.ref()
221
+ ref: ABBPropTypes.ref(),
222
+ /**
223
+ * If true, this individual button cannot be interacted with. Takes precedence
224
+ * over the group-level `inactive` prop. Useful for disabling specific options.
225
+ */
226
+ inactive: PropTypes.bool
220
227
  })),
221
228
  /**
222
229
  * If provided, this function is called when the current selection is changed
@@ -6,9 +6,9 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
6
6
  import Platform from "react-native-web/dist/exports/Platform";
7
7
  import Dimensions from "react-native-web/dist/exports/Dimensions";
8
8
  import PropTypes from 'prop-types';
9
- import { useThemeTokens } from '../ThemeProvider';
9
+ import { useThemeTokens, useTheme } from '../ThemeProvider';
10
10
  import { useViewport } from '../ViewportProvider';
11
- import { getTokensPropType, getA11yPropsFromHtmlTag, layoutTags, variantProp, selectSystemProps, a11yProps, viewProps, useCopy, unpackFragment, isTouchDevice } from '../utils';
11
+ import { getTokensPropType, getA11yPropsFromHtmlTag, layoutTags, variantProp, selectSystemProps, a11yProps, viewProps, useCopy, unpackFragment, isTouchDevice, useResponsiveProp, resolveContentMaxWidth } from '../utils';
12
12
  import { useA11yInfo } from '../A11yInfoProvider';
13
13
  import { CarouselProvider } from './CarouselContext';
14
14
  import CarouselItem from './CarouselItem';
@@ -203,11 +203,18 @@ const selectRootContainerStyles = (enableHero, viewport) => {
203
203
  }
204
204
  return {};
205
205
  };
206
- const selectMainContainerStyles = (enableHero, viewport) => {
206
+ const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
207
207
  if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
208
208
  return {
209
209
  width: '100%',
210
- maxWidth: 1200
210
+ maxWidth: maxWidth || 1200
211
+ };
212
+ }
213
+ if (maxWidth !== null && maxWidth !== undefined) {
214
+ return {
215
+ maxWidth,
216
+ alignSelf: 'center',
217
+ width: '100%'
211
218
  };
212
219
  }
213
220
  return {};
@@ -354,11 +361,18 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
354
361
  loopDuration = transitionDuration,
355
362
  autoPlay = false,
356
363
  enablePeeking = false,
364
+ contentMaxWidth,
357
365
  ...rest
358
366
  } = _ref3;
359
367
  let childrenArray = unpackFragment(children);
360
368
  const isTransitioningRef = React.useRef(false);
361
369
  const viewport = useViewport();
370
+ const {
371
+ themeOptions
372
+ } = useTheme();
373
+ const contentMaxWidthValue = useResponsiveProp(contentMaxWidth);
374
+ const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth);
375
+ const maxWidth = resolveContentMaxWidth(contentMaxWidthValue, responsiveWidth);
362
376
  const totalItems = getTotalItems(enableDisplayMultipleItemsPerSlide, childrenArray, viewport);
363
377
  const autoPlayFeatureEnabled = autoPlay && slideDuration > 0 && transitionDuration > 0 && totalItems > 1;
364
378
  // if `Carousel` only has one `Carousel.Item`, convert this to a single-item array
@@ -889,7 +903,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
889
903
  return /*#__PURE__*/_jsxs(View, {
890
904
  style: selectRootContainerStyles(enableHero, viewport),
891
905
  children: [/*#__PURE__*/_jsx(View, {
892
- style: selectMainContainerStyles(enableHero, viewport),
906
+ style: selectMainContainerStyles(enableHero, viewport, maxWidth),
893
907
  children: /*#__PURE__*/_jsxs(CarouselProvider, {
894
908
  activeIndex: activeIndex,
895
909
  goTo: goTo,
@@ -1247,7 +1261,24 @@ Carousel.propTypes = {
1247
1261
  * If set to `true`, the Carousel will show multiple slides at once
1248
1262
  * - Default value is `false`
1249
1263
  */
1250
- enableDisplayMultipleItemsPerSlide: PropTypes.bool
1264
+ enableDisplayMultipleItemsPerSlide: PropTypes.bool,
1265
+ /**
1266
+ * The maximum width of the content in the Carousel.
1267
+ * This prop accepts responsive values for different viewports. If a number is provided,
1268
+ * it will be the max content width for the desired viewport.
1269
+ * - `xs`: 'max' | 'full' | <number>
1270
+ * - `sm`: 'max' | 'full' | <number>
1271
+ * - `md`: 'max' | 'full' | <number>
1272
+ * - `lg`: 'max' | 'full' | <number>
1273
+ * - `xl`: 'max' | 'full' | <number>
1274
+ */
1275
+ contentMaxWidth: PropTypes.shape({
1276
+ xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1277
+ lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1278
+ md: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1279
+ sm: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1280
+ xs: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number])
1281
+ })
1251
1282
  };
1252
1283
  Carousel.Item = CarouselItem;
1253
1284
  Carousel.displayName = 'Carousel';
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { viewports } from '@telus-uds/system-constants';
4
4
  import { a11yProps, viewProps, getA11yPropsFromHtmlTag, layoutTags, selectSystemProps, BaseView, StyleSheet, createMediaQueryStyles, useResponsiveProp } from '../utils';
5
+ import resolveContentMaxWidth from '../utils/resolveContentMaxWidth';
5
6
  import Row from './Row';
6
7
  import Col from './Col';
7
8
  import GutterContext from './providers/GutterContext';
@@ -10,47 +11,24 @@ import { useTheme } from '../ThemeProvider';
10
11
  import { useViewport } from '../ViewportProvider';
11
12
  import { jsx as _jsx } from "react/jsx-runtime";
12
13
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
13
- const CONTENT_MAX_WIDTH = 'max';
14
- const CONTENT_FULL_WIDTH = 'full';
15
14
 
16
15
  /**
17
- * Resolves the maximum width for content based on the provided value and responsive width.
18
- *
19
- * @param {number|string|null|undefined} contentMinWidthValue - The minimum width value for the content.
20
- * Can be a number, a special string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
21
- * @param {number} responsiveWidth - The responsive width to use when contentMinWidthValue is CONTENT_MAX_WIDTH.
22
- * @returns {number|string|null} The resolved maximum width value, or null if full width is desired.
23
- */
24
- const resolveContentMaxWidth = (contentMinWidthValue, responsiveWidth) => {
25
- if (!contentMinWidthValue || contentMinWidthValue === CONTENT_FULL_WIDTH) {
26
- return null;
27
- }
28
- if (Number.isFinite(contentMinWidthValue)) {
29
- return contentMinWidthValue;
30
- }
31
- if (contentMinWidthValue === CONTENT_MAX_WIDTH) {
32
- return responsiveWidth;
33
- }
34
- return contentMinWidthValue;
35
- };
36
-
37
- /**
38
- * Calculates the maximum width for a given viewport based on limitWidth and contentMinWidth settings.
16
+ * Calculates the maximum width for a given viewport based on limitWidth and contentMaxWidth settings.
39
17
  *
40
18
  * @param {string} viewportKey - The viewport key ('xs', 'sm', 'md', 'lg', 'xl')
41
19
  * @param {boolean} limitWidth - Whether to limit the width to viewport breakpoints
42
- * @param {any} contentMinWidth - The contentMinWidth prop value
20
+ * @param {any} contentWidthProp - The contentMaxWidth (or contentMinWidth) prop value
43
21
  * @param {number|string|null} maxWidth - The resolved max width value
44
22
  * @returns {number|string|null} The calculated maximum width for the viewport
45
23
  */
46
- const getMaxWidthForViewport = (viewportKey, limitWidth, contentMinWidth, maxWidth) => {
24
+ const getMaxWidthForViewport = (viewportKey, limitWidth, contentWidthProp, maxWidth) => {
47
25
  if (limitWidth) {
48
26
  if (viewportKey === 'xs') {
49
27
  return null;
50
28
  }
51
29
  return viewports.map.get(viewportKey);
52
30
  }
53
- if (contentMinWidth) {
31
+ if (contentWidthProp) {
54
32
  return maxWidth;
55
33
  }
56
34
  return null;
@@ -74,6 +52,7 @@ const FlexGrid = /*#__PURE__*/React.forwardRef((_ref, ref) => {
74
52
  accessibilityRole,
75
53
  children,
76
54
  dataSet,
55
+ contentMaxWidth,
77
56
  contentMinWidth,
78
57
  ...rest
79
58
  } = _ref;
@@ -87,28 +66,31 @@ const FlexGrid = /*#__PURE__*/React.forwardRef((_ref, ref) => {
87
66
  } = useTheme();
88
67
  let flexgridStyles;
89
68
  let mediaIds;
90
- const contentMinWidthValue = useResponsiveProp(contentMinWidth);
69
+
70
+ // Support both contentMaxWidth and deprecated contentMinWidth for backwards compatibility
71
+ const contentWidthProp = contentMaxWidth || contentMinWidth;
72
+ const contentWidthValue = useResponsiveProp(contentWidthProp);
91
73
  const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth);
92
- const maxWidth = resolveContentMaxWidth(contentMinWidthValue, responsiveWidth);
74
+ const maxWidth = resolveContentMaxWidth(contentWidthValue, responsiveWidth);
93
75
  const stylesByViewport = {
94
76
  xs: {
95
- maxWidth: getMaxWidthForViewport('xs', limitWidth, contentMinWidth, maxWidth),
77
+ maxWidth: getMaxWidthForViewport('xs', limitWidth, contentWidthProp, maxWidth),
96
78
  flexDirection: reverseLevel[0] ? 'column-reverse' : 'column'
97
79
  },
98
80
  sm: {
99
- maxWidth: getMaxWidthForViewport('sm', limitWidth, contentMinWidth, maxWidth),
81
+ maxWidth: getMaxWidthForViewport('sm', limitWidth, contentWidthProp, maxWidth),
100
82
  flexDirection: reverseLevel[1] ? 'column-reverse' : 'column'
101
83
  },
102
84
  md: {
103
- maxWidth: getMaxWidthForViewport('md', limitWidth, contentMinWidth, maxWidth),
85
+ maxWidth: getMaxWidthForViewport('md', limitWidth, contentWidthProp, maxWidth),
104
86
  flexDirection: reverseLevel[2] ? 'column-reverse' : 'column'
105
87
  },
106
88
  lg: {
107
- maxWidth: getMaxWidthForViewport('lg', limitWidth, contentMinWidth, maxWidth),
89
+ maxWidth: getMaxWidthForViewport('lg', limitWidth, contentWidthProp, maxWidth),
108
90
  flexDirection: reverseLevel[3] ? 'column-reverse' : 'column'
109
91
  },
110
92
  xl: {
111
- maxWidth: getMaxWidthForViewport('xl', limitWidth, contentMinWidth, maxWidth),
93
+ maxWidth: getMaxWidthForViewport('xl', limitWidth, contentWidthProp, maxWidth),
112
94
  flexDirection: reverseLevel[4] ? 'column-reverse' : 'column'
113
95
  }
114
96
  };
@@ -204,7 +186,7 @@ FlexGrid.propTypes = {
204
186
  */
205
187
  children: PropTypes.node.isRequired,
206
188
  /**
207
- * The minimum width of the content in the FlexGrid.
189
+ * The maximum width of the content in the FlexGrid.
208
190
  * This prop accepts responsive values for different viewports. If a number is provided,
209
191
  * it will be the max content width for the desired viewport.
210
192
  * - `xs`: 'max' | 'full' | <number>
@@ -213,6 +195,20 @@ FlexGrid.propTypes = {
213
195
  * - `lg`: 'max' | 'full' | <number>
214
196
  * - `xl`: 'max' | 'full' | <number>
215
197
  */
198
+ contentMaxWidth: PropTypes.shape({
199
+ xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
200
+ lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
201
+ md: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
202
+ sm: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
203
+ xs: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number])
204
+ }),
205
+ /**
206
+ * @deprecated Use `contentMaxWidth` instead. This prop will be removed in a future version.
207
+ *
208
+ * The minimum width of the content in the FlexGrid.
209
+ * This prop accepts responsive values for different viewports. If a number is provided,
210
+ * it will be the max content width for the desired viewport.
211
+ */
216
212
  contentMinWidth: PropTypes.shape({
217
213
  xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
218
214
  lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
@@ -123,6 +123,7 @@ const IconButton = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
123
123
  hrefAttrs,
124
124
  testID,
125
125
  accessibilityRole = href ? 'link' : 'button',
126
+ inactive = false,
126
127
  ...rawRest
127
128
  } = _ref3;
128
129
  const {
@@ -143,8 +144,12 @@ const IconButton = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
143
144
  }
144
145
  });
145
146
  };
146
- const getTokens = useThemeTokensCallback('IconButton', tokens, variant);
147
- const getOuterStyle = pressableState => selectOuterStyle(getTokens(resolvePressableState(pressableState), variant.password));
147
+ const mergedVariant = inactive ? {
148
+ ...variant,
149
+ inactive: true
150
+ } : variant;
151
+ const getTokens = useThemeTokensCallback('IconButton', tokens, mergedVariant);
152
+ const getOuterStyle = pressableState => selectOuterStyle(getTokens(resolvePressableState(pressableState), mergedVariant.password));
148
153
  return /*#__PURE__*/_jsx(Pressable, {
149
154
  ref: ref,
150
155
  href: href,
@@ -153,15 +158,16 @@ const IconButton = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
153
158
  style: getOuterStyle,
154
159
  ...selectedProps,
155
160
  testID: testID,
161
+ disabled: inactive,
156
162
  children: pressableState => {
157
163
  const themeTokens = getTokens(resolvePressableState(pressableState));
158
164
  return /*#__PURE__*/_jsx(View, {
159
- style: selectInnerStyle(themeTokens, variant.password),
165
+ style: selectInnerStyle(themeTokens, mergedVariant.password),
160
166
  children: /*#__PURE__*/_jsx(Icon, {
161
167
  icon: IconComponent || themeTokens.icon,
162
168
  title: selectedProps.accessibilityLabel,
163
169
  tokens: selectTokens('Icon', themeTokens, 'icon'),
164
- variant: variant
170
+ variant: mergedVariant
165
171
  })
166
172
  });
167
173
  }
@@ -192,7 +198,11 @@ IconButton.propTypes = {
192
198
  /**
193
199
  * Function to execute when the `Iconbutton` is pressed
194
200
  */
195
- onPress: PropTypes.func
201
+ onPress: PropTypes.func,
202
+ /**
203
+ * When true, applies the inactive variant styling
204
+ */
205
+ inactive: PropTypes.bool
196
206
  };
197
207
  const staticStyles = StyleSheet.create({
198
208
  outer: {
@@ -325,7 +325,7 @@ const TextInputBase = /*#__PURE__*/React.forwardRef((_ref8, ref) => {
325
325
  icon: ClearButtonIcon,
326
326
  onPress: handleClear,
327
327
  variant: {
328
- compact: true
328
+ subtle: true
329
329
  }
330
330
  }, "clear"));
331
331
  }
@@ -335,8 +335,7 @@ const TextInputBase = /*#__PURE__*/React.forwardRef((_ref8, ref) => {
335
335
  icon: !showPassword ? passwordShowButtonIcon : passwordHideButtonIcon,
336
336
  onPress: handleShowOrHide,
337
337
  variant: {
338
- compact: true,
339
- password: true,
338
+ subtle: true,
340
339
  inactive: variant.inactive,
341
340
  size: 'large'
342
341
  },
@@ -26,4 +26,5 @@ export { default as convertFromMegaByteToByte } from './convertFromMegaByteToByt
26
26
  export { default as formatImageSource } from './formatImageSource';
27
27
  export { default as getSpacingScale } from './getSpacingScale';
28
28
  export { default as useVariants } from './useVariants';
29
- export { default as isTouchDevice } from './isTouchDevice';
29
+ export { default as isTouchDevice } from './isTouchDevice';
30
+ export { default as resolveContentMaxWidth } from './resolveContentMaxWidth';
@@ -0,0 +1,24 @@
1
+ const CONTENT_MAX_WIDTH = 'max';
2
+ const CONTENT_FULL_WIDTH = 'full';
3
+
4
+ /**
5
+ * Resolves the maximum width for content based on the provided value and responsive width.
6
+ *
7
+ * @param {number|string|null|undefined} contentMaxWidthValue - The maximum width value for the content.
8
+ * Can be a number, a special string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
9
+ * @param {number} responsiveWidth - The responsive width to use when contentMaxWidthValue is CONTENT_MAX_WIDTH.
10
+ * @returns {number|string|null} The resolved maximum width value, or null if full width is desired.
11
+ */
12
+ const resolveContentMaxWidth = (contentMaxWidthValue, responsiveWidth) => {
13
+ if (!contentMaxWidthValue || contentMaxWidthValue === CONTENT_FULL_WIDTH) {
14
+ return null;
15
+ }
16
+ if (Number.isFinite(contentMaxWidthValue)) {
17
+ return contentMaxWidthValue;
18
+ }
19
+ if (contentMaxWidthValue === CONTENT_MAX_WIDTH) {
20
+ return responsiveWidth;
21
+ }
22
+ return contentMaxWidthValue;
23
+ };
24
+ export default resolveContentMaxWidth;
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.17.0",
15
+ "@telus-uds/system-theme-tokens": "^4.18.0",
16
16
  "airbnb-prop-types": "^2.16.0",
17
17
  "css-mediaquery": "^0.1.2",
18
18
  "expo-document-picker": "^13.0.1",
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.24.0",
87
+ "version": "3.25.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.17.0",
15
+ "@telus-uds/system-theme-tokens": "^4.18.0",
16
16
  "airbnb-prop-types": "^2.16.0",
17
17
  "css-mediaquery": "^0.1.2",
18
18
  "expo-document-picker": "^13.0.1",
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.24.0",
87
+ "version": "3.25.0",
88
88
  "types": "types/index.d.ts"
89
89
  }
@@ -151,7 +151,17 @@ const ButtonGroup = React.forwardRef(
151
151
  >
152
152
  <View accessibilityRole={innerRole} style={viewStyles}>
153
153
  {items.map(
154
- ({ label, id = label, accessibilityLabel, ref: itemRef, ...itemRest }, index) => {
154
+ (
155
+ {
156
+ label,
157
+ id = label,
158
+ accessibilityLabel,
159
+ ref: itemRef,
160
+ inactive: itemInactive,
161
+ ...itemRest
162
+ },
163
+ index
164
+ ) => {
155
165
  const isSelected = currentValues.includes(id)
156
166
 
157
167
  // Pass an object of relevant component state as first argument for any passed-in press handlers
@@ -171,6 +181,8 @@ const ButtonGroup = React.forwardRef(
171
181
  ...a11yProps.getPositionInSet(items.length, index)
172
182
  }
173
183
 
184
+ const isInactive = itemInactive !== undefined ? itemInactive : inactive
185
+
174
186
  // Ensure button is direct child of group as MacOS voiceover only applies "X of Y" to
175
187
  // "radio" if it's a direct child of "radiogroup", even if aria-posinset etc exists
176
188
  return (
@@ -182,7 +194,7 @@ const ButtonGroup = React.forwardRef(
182
194
  onPress={handlePress}
183
195
  tokens={getButtonTokens}
184
196
  selected={isSelected}
185
- inactive={inactive}
197
+ inactive={isInactive}
186
198
  icon={iconProp}
187
199
  {...selectItemProps({
188
200
  ...itemRest,
@@ -243,7 +255,12 @@ ButtonGroup.propTypes = {
243
255
  /**
244
256
  * An optional ref for one individual button in the ButtonGroup
245
257
  */
246
- ref: ABBPropTypes.ref()
258
+ ref: ABBPropTypes.ref(),
259
+ /**
260
+ * If true, this individual button cannot be interacted with. Takes precedence
261
+ * over the group-level `inactive` prop. Useful for disabling specific options.
262
+ */
263
+ inactive: PropTypes.bool
247
264
  })
248
265
  ),
249
266
  /**
@@ -1,7 +1,7 @@
1
1
  import React from 'react'
2
2
  import { View, Animated, PanResponder, StyleSheet, Platform, Dimensions } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
- import { useThemeTokens } from '../ThemeProvider'
4
+ import { useThemeTokens, useTheme } from '../ThemeProvider'
5
5
  import { useViewport } from '../ViewportProvider'
6
6
  import {
7
7
  getTokensPropType,
@@ -13,7 +13,9 @@ import {
13
13
  viewProps,
14
14
  useCopy,
15
15
  unpackFragment,
16
- isTouchDevice
16
+ isTouchDevice,
17
+ useResponsiveProp,
18
+ resolveContentMaxWidth
17
19
  } from '../utils'
18
20
  import { useA11yInfo } from '../A11yInfoProvider'
19
21
  import { CarouselProvider } from './CarouselContext'
@@ -252,11 +254,18 @@ const selectRootContainerStyles = (enableHero, viewport) => {
252
254
  return {}
253
255
  }
254
256
 
255
- const selectMainContainerStyles = (enableHero, viewport) => {
257
+ const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
256
258
  if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
257
259
  return {
258
260
  width: '100%',
259
- maxWidth: 1200
261
+ maxWidth: maxWidth || 1200
262
+ }
263
+ }
264
+ if (maxWidth !== null && maxWidth !== undefined) {
265
+ return {
266
+ maxWidth,
267
+ alignSelf: 'center',
268
+ width: '100%'
260
269
  }
261
270
  }
262
271
  return {}
@@ -402,6 +411,7 @@ const Carousel = React.forwardRef(
402
411
  loopDuration = transitionDuration,
403
412
  autoPlay = false,
404
413
  enablePeeking = false,
414
+ contentMaxWidth,
405
415
  ...rest
406
416
  },
407
417
  ref
@@ -409,6 +419,11 @@ const Carousel = React.forwardRef(
409
419
  let childrenArray = unpackFragment(children)
410
420
  const isTransitioningRef = React.useRef(false)
411
421
  const viewport = useViewport()
422
+ const { themeOptions } = useTheme()
423
+
424
+ const contentMaxWidthValue = useResponsiveProp(contentMaxWidth)
425
+ const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth)
426
+ const maxWidth = resolveContentMaxWidth(contentMaxWidthValue, responsiveWidth)
412
427
  const totalItems = getTotalItems(enableDisplayMultipleItemsPerSlide, childrenArray, viewport)
413
428
  const autoPlayFeatureEnabled =
414
429
  autoPlay && slideDuration > 0 && transitionDuration > 0 && totalItems > 1
@@ -1031,7 +1046,7 @@ const Carousel = React.forwardRef(
1031
1046
 
1032
1047
  return (
1033
1048
  <View style={selectRootContainerStyles(enableHero, viewport)}>
1034
- <View style={selectMainContainerStyles(enableHero, viewport)}>
1049
+ <View style={selectMainContainerStyles(enableHero, viewport, maxWidth)}>
1035
1050
  <CarouselProvider
1036
1051
  activeIndex={activeIndex}
1037
1052
  goTo={goTo}
@@ -1463,7 +1478,24 @@ Carousel.propTypes = {
1463
1478
  * If set to `true`, the Carousel will show multiple slides at once
1464
1479
  * - Default value is `false`
1465
1480
  */
1466
- enableDisplayMultipleItemsPerSlide: PropTypes.bool
1481
+ enableDisplayMultipleItemsPerSlide: PropTypes.bool,
1482
+ /**
1483
+ * The maximum width of the content in the Carousel.
1484
+ * This prop accepts responsive values for different viewports. If a number is provided,
1485
+ * it will be the max content width for the desired viewport.
1486
+ * - `xs`: 'max' | 'full' | <number>
1487
+ * - `sm`: 'max' | 'full' | <number>
1488
+ * - `md`: 'max' | 'full' | <number>
1489
+ * - `lg`: 'max' | 'full' | <number>
1490
+ * - `xl`: 'max' | 'full' | <number>
1491
+ */
1492
+ contentMaxWidth: PropTypes.shape({
1493
+ xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1494
+ lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1495
+ md: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1496
+ sm: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
1497
+ xs: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number])
1498
+ })
1467
1499
  }
1468
1500
 
1469
1501
  Carousel.Item = CarouselItem
@@ -13,6 +13,7 @@ import {
13
13
  createMediaQueryStyles,
14
14
  useResponsiveProp
15
15
  } from '../utils'
16
+ import resolveContentMaxWidth from '../utils/resolveContentMaxWidth'
16
17
  import Row from './Row'
17
18
  import Col from './Col'
18
19
  import GutterContext from './providers/GutterContext'
@@ -22,43 +23,16 @@ import { useViewport } from '../ViewportProvider'
22
23
 
23
24
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
24
25
 
25
- const CONTENT_MAX_WIDTH = 'max'
26
- const CONTENT_FULL_WIDTH = 'full'
27
-
28
- /**
29
- * Resolves the maximum width for content based on the provided value and responsive width.
30
- *
31
- * @param {number|string|null|undefined} contentMinWidthValue - The minimum width value for the content.
32
- * Can be a number, a special string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
33
- * @param {number} responsiveWidth - The responsive width to use when contentMinWidthValue is CONTENT_MAX_WIDTH.
34
- * @returns {number|string|null} The resolved maximum width value, or null if full width is desired.
35
- */
36
- const resolveContentMaxWidth = (contentMinWidthValue, responsiveWidth) => {
37
- if (!contentMinWidthValue || contentMinWidthValue === CONTENT_FULL_WIDTH) {
38
- return null
39
- }
40
-
41
- if (Number.isFinite(contentMinWidthValue)) {
42
- return contentMinWidthValue
43
- }
44
-
45
- if (contentMinWidthValue === CONTENT_MAX_WIDTH) {
46
- return responsiveWidth
47
- }
48
-
49
- return contentMinWidthValue
50
- }
51
-
52
26
  /**
53
- * Calculates the maximum width for a given viewport based on limitWidth and contentMinWidth settings.
27
+ * Calculates the maximum width for a given viewport based on limitWidth and contentMaxWidth settings.
54
28
  *
55
29
  * @param {string} viewportKey - The viewport key ('xs', 'sm', 'md', 'lg', 'xl')
56
30
  * @param {boolean} limitWidth - Whether to limit the width to viewport breakpoints
57
- * @param {any} contentMinWidth - The contentMinWidth prop value
31
+ * @param {any} contentWidthProp - The contentMaxWidth (or contentMinWidth) prop value
58
32
  * @param {number|string|null} maxWidth - The resolved max width value
59
33
  * @returns {number|string|null} The calculated maximum width for the viewport
60
34
  */
61
- const getMaxWidthForViewport = (viewportKey, limitWidth, contentMinWidth, maxWidth) => {
35
+ const getMaxWidthForViewport = (viewportKey, limitWidth, contentWidthProp, maxWidth) => {
62
36
  if (limitWidth) {
63
37
  if (viewportKey === 'xs') {
64
38
  return null
@@ -66,7 +40,7 @@ const getMaxWidthForViewport = (viewportKey, limitWidth, contentMinWidth, maxWid
66
40
  return viewports.map.get(viewportKey)
67
41
  }
68
42
 
69
- if (contentMinWidth) {
43
+ if (contentWidthProp) {
70
44
  return maxWidth
71
45
  }
72
46
 
@@ -92,6 +66,7 @@ const FlexGrid = React.forwardRef(
92
66
  accessibilityRole,
93
67
  children,
94
68
  dataSet,
69
+ contentMaxWidth,
95
70
  contentMinWidth,
96
71
  ...rest
97
72
  },
@@ -107,29 +82,31 @@ const FlexGrid = React.forwardRef(
107
82
  let flexgridStyles
108
83
  let mediaIds
109
84
 
110
- const contentMinWidthValue = useResponsiveProp(contentMinWidth)
85
+ // Support both contentMaxWidth and deprecated contentMinWidth for backwards compatibility
86
+ const contentWidthProp = contentMaxWidth || contentMinWidth
87
+ const contentWidthValue = useResponsiveProp(contentWidthProp)
111
88
  const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth)
112
- const maxWidth = resolveContentMaxWidth(contentMinWidthValue, responsiveWidth)
89
+ const maxWidth = resolveContentMaxWidth(contentWidthValue, responsiveWidth)
113
90
 
114
91
  const stylesByViewport = {
115
92
  xs: {
116
- maxWidth: getMaxWidthForViewport('xs', limitWidth, contentMinWidth, maxWidth),
93
+ maxWidth: getMaxWidthForViewport('xs', limitWidth, contentWidthProp, maxWidth),
117
94
  flexDirection: reverseLevel[0] ? 'column-reverse' : 'column'
118
95
  },
119
96
  sm: {
120
- maxWidth: getMaxWidthForViewport('sm', limitWidth, contentMinWidth, maxWidth),
97
+ maxWidth: getMaxWidthForViewport('sm', limitWidth, contentWidthProp, maxWidth),
121
98
  flexDirection: reverseLevel[1] ? 'column-reverse' : 'column'
122
99
  },
123
100
  md: {
124
- maxWidth: getMaxWidthForViewport('md', limitWidth, contentMinWidth, maxWidth),
101
+ maxWidth: getMaxWidthForViewport('md', limitWidth, contentWidthProp, maxWidth),
125
102
  flexDirection: reverseLevel[2] ? 'column-reverse' : 'column'
126
103
  },
127
104
  lg: {
128
- maxWidth: getMaxWidthForViewport('lg', limitWidth, contentMinWidth, maxWidth),
105
+ maxWidth: getMaxWidthForViewport('lg', limitWidth, contentWidthProp, maxWidth),
129
106
  flexDirection: reverseLevel[3] ? 'column-reverse' : 'column'
130
107
  },
131
108
  xl: {
132
- maxWidth: getMaxWidthForViewport('xl', limitWidth, contentMinWidth, maxWidth),
109
+ maxWidth: getMaxWidthForViewport('xl', limitWidth, contentWidthProp, maxWidth),
133
110
  flexDirection: reverseLevel[4] ? 'column-reverse' : 'column'
134
111
  }
135
112
  }
@@ -223,7 +200,7 @@ FlexGrid.propTypes = {
223
200
  */
224
201
  children: PropTypes.node.isRequired,
225
202
  /**
226
- * The minimum width of the content in the FlexGrid.
203
+ * The maximum width of the content in the FlexGrid.
227
204
  * This prop accepts responsive values for different viewports. If a number is provided,
228
205
  * it will be the max content width for the desired viewport.
229
206
  * - `xs`: 'max' | 'full' | <number>
@@ -232,6 +209,20 @@ FlexGrid.propTypes = {
232
209
  * - `lg`: 'max' | 'full' | <number>
233
210
  * - `xl`: 'max' | 'full' | <number>
234
211
  */
212
+ contentMaxWidth: PropTypes.shape({
213
+ xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
214
+ lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
215
+ md: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
216
+ sm: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
217
+ xs: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number])
218
+ }),
219
+ /**
220
+ * @deprecated Use `contentMaxWidth` instead. This prop will be removed in a future version.
221
+ *
222
+ * The minimum width of the content in the FlexGrid.
223
+ * This prop accepts responsive values for different viewports. If a number is provided,
224
+ * it will be the max content width for the desired viewport.
225
+ */
235
226
  contentMinWidth: PropTypes.shape({
236
227
  xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
237
228
  lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
@@ -136,6 +136,7 @@ const IconButton = React.forwardRef(
136
136
  hrefAttrs,
137
137
  testID,
138
138
  accessibilityRole = href ? 'link' : 'button',
139
+ inactive = false,
139
140
  ...rawRest
140
141
  },
141
142
  ref
@@ -149,9 +150,10 @@ const IconButton = React.forwardRef(
149
150
  linkProps.handleHref({ href, onPress })({ nativeEvent: { target: ref?.current?.id } })
150
151
  }
151
152
 
152
- const getTokens = useThemeTokensCallback('IconButton', tokens, variant)
153
+ const mergedVariant = inactive ? { ...variant, inactive: true } : variant
154
+ const getTokens = useThemeTokensCallback('IconButton', tokens, mergedVariant)
153
155
  const getOuterStyle = (pressableState) =>
154
- selectOuterStyle(getTokens(resolvePressableState(pressableState), variant.password))
156
+ selectOuterStyle(getTokens(resolvePressableState(pressableState), mergedVariant.password))
155
157
 
156
158
  return (
157
159
  <Pressable
@@ -162,16 +164,17 @@ const IconButton = React.forwardRef(
162
164
  style={getOuterStyle}
163
165
  {...selectedProps}
164
166
  testID={testID}
167
+ disabled={inactive}
165
168
  >
166
169
  {(pressableState) => {
167
170
  const themeTokens = getTokens(resolvePressableState(pressableState))
168
171
  return (
169
- <View style={selectInnerStyle(themeTokens, variant.password)}>
172
+ <View style={selectInnerStyle(themeTokens, mergedVariant.password)}>
170
173
  <Icon
171
174
  icon={IconComponent || themeTokens.icon}
172
175
  title={selectedProps.accessibilityLabel}
173
176
  tokens={selectTokens('Icon', themeTokens, 'icon')}
174
- variant={variant}
177
+ variant={mergedVariant}
175
178
  />
176
179
  </View>
177
180
  )
@@ -206,7 +209,11 @@ IconButton.propTypes = {
206
209
  /**
207
210
  * Function to execute when the `Iconbutton` is pressed
208
211
  */
209
- onPress: PropTypes.func
212
+ onPress: PropTypes.func,
213
+ /**
214
+ * When true, applies the inactive variant styling
215
+ */
216
+ inactive: PropTypes.bool
210
217
  }
211
218
 
212
219
  const staticStyles = StyleSheet.create({
@@ -313,7 +313,7 @@ const TextInputBase = React.forwardRef(
313
313
  icon={ClearButtonIcon}
314
314
  key="clear"
315
315
  onPress={handleClear}
316
- variant={{ compact: true }}
316
+ variant={{ subtle: true }}
317
317
  />
318
318
  )
319
319
  }
@@ -329,7 +329,7 @@ const TextInputBase = React.forwardRef(
329
329
  icon={!showPassword ? passwordShowButtonIcon : passwordHideButtonIcon}
330
330
  key={!showPassword ? 'hide' : 'show'}
331
331
  onPress={handleShowOrHide}
332
- variant={{ compact: true, password: true, inactive: variant.inactive, size: 'large' }}
332
+ variant={{ subtle: true, inactive: variant.inactive, size: 'large' }}
333
333
  tokens={{ width: 40, height: 40 }}
334
334
  />
335
335
  )
@@ -27,3 +27,4 @@ export { default as formatImageSource } from './formatImageSource'
27
27
  export { default as getSpacingScale } from './getSpacingScale'
28
28
  export { default as useVariants } from './useVariants'
29
29
  export { default as isTouchDevice } from './isTouchDevice'
30
+ export { default as resolveContentMaxWidth } from './resolveContentMaxWidth'
@@ -0,0 +1,28 @@
1
+ const CONTENT_MAX_WIDTH = 'max'
2
+ const CONTENT_FULL_WIDTH = 'full'
3
+
4
+ /**
5
+ * Resolves the maximum width for content based on the provided value and responsive width.
6
+ *
7
+ * @param {number|string|null|undefined} contentMaxWidthValue - The maximum width value for the content.
8
+ * Can be a number, a special string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
9
+ * @param {number} responsiveWidth - The responsive width to use when contentMaxWidthValue is CONTENT_MAX_WIDTH.
10
+ * @returns {number|string|null} The resolved maximum width value, or null if full width is desired.
11
+ */
12
+ const resolveContentMaxWidth = (contentMaxWidthValue, responsiveWidth) => {
13
+ if (!contentMaxWidthValue || contentMaxWidthValue === CONTENT_FULL_WIDTH) {
14
+ return null
15
+ }
16
+
17
+ if (Number.isFinite(contentMaxWidthValue)) {
18
+ return contentMaxWidthValue
19
+ }
20
+
21
+ if (contentMaxWidthValue === CONTENT_MAX_WIDTH) {
22
+ return responsiveWidth
23
+ }
24
+
25
+ return contentMaxWidthValue
26
+ }
27
+
28
+ export default resolveContentMaxWidth
@@ -0,0 +1,42 @@
1
+ import type { Variant } from '../../components-web/types/common'
2
+ import { ComponentType, ReactNode } from 'react'
3
+
4
+ import { IconProps } from './Icon'
5
+
6
+ export type StatusTokensProps = {
7
+ backgroundColor: string
8
+ backgroundGradient: string
9
+ borderColor: string
10
+ borderRadius: number | string
11
+ borderWidth: number | string
12
+ fontName: string
13
+ fontSize: number | string
14
+ fontWeight: number | string
15
+ icon: IconProps
16
+ iconColor: string
17
+ iconGradient: string
18
+ marginLeft: string | number
19
+ paddingBottom: string | number
20
+ paddingLeft: string | number
21
+ paddingRight: string | number
22
+ paddingTop: string | number
23
+ textColor: string
24
+ textLineHeight: string | number
25
+ iconSize: number | string
26
+ iconPaddingTop: number | string
27
+ }
28
+
29
+ export interface StatusProps {
30
+ children: ReactNode
31
+ variant?: Variant
32
+ tokens?: Partial<StatusTokensProps>
33
+ customGradient?: (
34
+ gradient: { colors: string[]; start: { x: number; y: number }; end: { x: number; y: number } },
35
+ styles: Record<string, unknown>,
36
+ content: ReactNode
37
+ ) => ReactNode
38
+ }
39
+
40
+ declare const Status: ComponentType<StatusProps>
41
+
42
+ export default Status
package/types/index.d.ts CHANGED
@@ -90,4 +90,7 @@ export { PortalProps } from './Portal'
90
90
  export { default as Listbox } from './Listbox'
91
91
  export { ListboxProps, ListboxTokens } from './Listbox'
92
92
 
93
+ export { default as Status } from './Status'
94
+ export { StatusProps, StatusTokensProps } from './Status'
95
+
93
96
  export * from './Common'