@telus-uds/components-web 4.17.0 → 4.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,12 +1,44 @@
1
1
  # Change Log - @telus-uds/components-web
2
2
 
3
- This log was last generated on Mon, 19 Jan 2026 20:39:51 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 18 Feb 2026 02:50:19 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 4.18.1
8
+
9
+ Wed, 18 Feb 2026 02:50:19 GMT
10
+
11
+ ### Patches
12
+
13
+ - refactor: simplify cardBaseTokens object creation by removing redundant destructuring (josue.higueroscalderon@telus.com)
14
+ - `IconButton`: Update stories (david.melara1@telus.com)
15
+ - `Card`: background image hidden behind the default color issue fixed (josue.higueroscalderon@telus.com)
16
+ - Bump @telus-uds/components-base to v3.28.0
17
+ - Bump @telus-uds/system-theme-tokens to v4.20.0
18
+
19
+ ## 4.18.0
20
+
21
+ Thu, 29 Jan 2026 15:50:17 GMT
22
+
23
+ ### Minor changes
24
+
25
+ - `List`: new feature alignment for the icons added (josue.higueroscalderon@telus.com)
26
+ - `Card`: Add full-bleed content support to Card component allowing content to extend to card edges (josue.higueroscalderon@telus.com)
27
+ - `QuantitySelector`: add inactive prop (guillermo.peitzner@telus.com)
28
+ - `Card`: Unnecessary comments removed. (josue.higueroscalderon@telus.com)
29
+ - `NavigationBar`: add contentMaxWidth prop (guillermo.peitzner@telus.com)
30
+ - Bump @telus-uds/components-base to v3.27.0
31
+ - Bump @telus-uds/system-theme-tokens to v4.19.0
32
+
33
+ ### Patches
34
+
35
+ - `QuantitySelector`: spacer alignment issue fixed (josue.higueroscalderon@telus.com)
36
+ - `NavigationBar`: fix console warning (guillermo.peitzner@telus.com)
37
+ - `Card`: component enhaced to manage the hover, focus and pressed states of interactiveCard properly (josue.higueroscalderon@telus.com)
38
+
7
39
  ## 4.17.0
8
40
 
9
- Mon, 19 Jan 2026 20:39:51 GMT
41
+ Mon, 19 Jan 2026 20:01:22 GMT
10
42
 
11
43
  ### Minor changes
12
44
 
@@ -15,7 +47,7 @@ Mon, 19 Jan 2026 20:39:51 GMT
15
47
 
16
48
  ### Patches
17
49
 
18
- - `NavigationBar`: Fix flickering from overlay overflow (david.melara1@telus.com)
50
+ - `NavigationBar`: Fix flickering from overlay overflow (david.melara1@telus.com)
19
51
 
20
52
  ## 4.16.0
21
53
 
@@ -19,6 +19,61 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
19
19
  // Passes React Native-oriented system props through UDS Card
20
20
  const [selectProps, selectedSystemPropTypes] = (0, _componentsBase.selectSystemProps)([_componentsBase.a11yProps, _componentsBase.viewProps]);
21
21
  const GRID_COLUMNS = 12;
22
+ const POSITION = {
23
+ LEFT: 'left',
24
+ RIGHT: 'right',
25
+ TOP: 'top',
26
+ BOTTOM: 'bottom',
27
+ NONE: 'none'
28
+ };
29
+
30
+ /**
31
+ * Helper function to get StackView tokens
32
+ * @param {Object} columnFlex - Column flex properties
33
+ * @param {string} contentStackAlign - Alignment value for content stack
34
+ * @returns {Object} StackView tokens object
35
+ */
36
+ const getStackViewTokens = (columnFlex, contentStackAlign) => ({
37
+ ...columnFlex,
38
+ alignItems: contentStackAlign
39
+ });
40
+
41
+ /**
42
+ * Helper function to get CardContent tokens
43
+ * @param {Object} baseTokens - Base tokens to spread
44
+ * @param {Object} options - Options object
45
+ * @param {boolean} options.backgroundImage - Whether background image is present
46
+ * @param {string} options.fullBleedContentChildrenAlign - Alignment for full bleed content children
47
+ * @param {boolean} options.useTransparentBackground - Whether to use transparent background when no backgroundImage
48
+ * @returns {Object} CardContent tokens object
49
+ */
50
+ const getCardContentTokens = function (baseTokens) {
51
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
52
+ const {
53
+ backgroundImage,
54
+ fullBleedContentChildrenAlign,
55
+ useTransparentBackground
56
+ } = options;
57
+
58
+ // Determine background color based on conditions
59
+ let backgroundColorOverride = {};
60
+ if (useTransparentBackground) {
61
+ backgroundColorOverride = {
62
+ backgroundColor: 'transparent'
63
+ };
64
+ } else if (backgroundImage) {
65
+ backgroundColorOverride = {
66
+ backgroundColor: 'transparent'
67
+ };
68
+ }
69
+ return {
70
+ ...baseTokens,
71
+ ...backgroundColorOverride,
72
+ ...(fullBleedContentChildrenAlign && {
73
+ alignSelf: fullBleedContentChildrenAlign
74
+ })
75
+ };
76
+ };
22
77
 
23
78
  /**
24
79
  * A basic card component, unstyled by default.
@@ -77,6 +132,59 @@ const DynamicWidthContainer = /*#__PURE__*/_styledComponents.default.div.withCon
77
132
  alignSelf
78
133
  };
79
134
  });
135
+ const InteractiveCardWrapper = /*#__PURE__*/_styledComponents.default.div.withConfig({
136
+ displayName: "Card__InteractiveCardWrapper",
137
+ componentId: "components-web__sc-1elbtwd-1"
138
+ })(() => ({
139
+ position: 'relative',
140
+ flex: 1,
141
+ display: 'flex',
142
+ flexDirection: 'column'
143
+ }));
144
+ const InteractiveOverlay = /*#__PURE__*/_styledComponents.default.div.withConfig({
145
+ displayName: "Card__InteractiveOverlay",
146
+ componentId: "components-web__sc-1elbtwd-2"
147
+ })(_ref2 => {
148
+ let {
149
+ overlayOpacity,
150
+ borderRadius
151
+ } = _ref2;
152
+ return {
153
+ position: 'absolute',
154
+ top: 0,
155
+ left: 0,
156
+ right: 0,
157
+ bottom: 0,
158
+ backgroundColor: `rgba(0, 0, 0, ${overlayOpacity || 0})`,
159
+ borderRadius,
160
+ pointerEvents: 'none',
161
+ transition: 'background-color 0.2s ease',
162
+ zIndex: 1
163
+ };
164
+ });
165
+ const FocusBorder = /*#__PURE__*/_styledComponents.default.div.withConfig({
166
+ displayName: "Card__FocusBorder",
167
+ componentId: "components-web__sc-1elbtwd-3"
168
+ })(_ref3 => {
169
+ let {
170
+ borderWidth,
171
+ borderColor,
172
+ borderRadius
173
+ } = _ref3;
174
+ return {
175
+ position: 'absolute',
176
+ top: 0,
177
+ left: 0,
178
+ right: 0,
179
+ bottom: 0,
180
+ borderWidth,
181
+ borderColor,
182
+ borderRadius,
183
+ borderStyle: 'solid',
184
+ pointerEvents: 'none',
185
+ zIndex: 2
186
+ };
187
+ });
80
188
  const Card = /*#__PURE__*/_react.default.forwardRef(function () {
81
189
  let {
82
190
  children,
@@ -126,39 +234,87 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
126
234
 
127
235
  // If the card has rounded corners and a full bleed image, we need to apply
128
236
  // those corners on the image as well, but partially
129
- const allThemeTokens = (0, _componentsBase.useThemeTokens)('Card', tokens, variant);
237
+ const variantForTokens = backgroundImage ? {
238
+ ...variant,
239
+ style: undefined
240
+ } : variant;
241
+ const allThemeTokens = (0, _componentsBase.useThemeTokens)('Card', tokens, variantForTokens);
130
242
  const {
131
243
  borderRadius
132
244
  } = allThemeTokens;
133
- const cardBaseBorderWidth = allThemeTokens.borderWidth;
134
- const pressableBorderWidth = (0, _componentsBase.useThemeTokens)('Card', {}, {
245
+
246
+ // Interactive cards: merge variants for CardBase (outer container)
247
+ // The outer variant takes priority over interactiveCard.variant for the style property
248
+ // This ensures the gradient is only applied to CardBase, not PressableCardBase and avoid duplication
249
+ const interactiveStyle = interactiveCard?.variant?.style;
250
+ const outerStyle = variant?.style;
251
+ const mergedVariant = {
252
+ ...variant,
253
+ style: outerStyle || interactiveStyle
254
+ };
255
+
256
+ // Interactive cards: build configuration for PressableCardBase
257
+ // This determines which style to use for interactive states (hover, pressed, etc.)
258
+ // without causing gradient duplication
259
+ let interactiveCardConfig = {};
260
+ if (interactiveCard?.body) {
261
+ const styleToUse = interactiveCard?.variant?.style || variant?.style;
262
+ const {
263
+ style,
264
+ ...otherVariantProps
265
+ } = interactiveCard?.variant || {};
266
+ interactiveCardConfig = {
267
+ interactive: true,
268
+ ...(styleToUse && {
269
+ style: styleToUse
270
+ }),
271
+ ...otherVariantProps
272
+ };
273
+ }
274
+ const getThemeTokensBase = (0, _componentsBase.useThemeTokensCallback)('Card', interactiveCard?.tokens, interactiveCardConfig);
275
+
276
+ // Wrap getThemeTokens to remove gradient from resolved tokens
277
+ // PressableCardBase calls this function with pressableState (hover, pressed, etc.)
278
+ // We intercept the resolved tokens and remove gradient properties to prevent duplication
279
+ // since the gradient should only appear on CardBase (outer container)
280
+ const getThemeTokens = _react.default.useCallback(pressableState => {
281
+ const resolvedTokens = getThemeTokensBase(pressableState);
282
+ const {
283
+ gradient,
284
+ backgroundGradient,
285
+ ...tokensWithoutGradient
286
+ } = resolvedTokens;
287
+ return tokensWithoutGradient;
288
+ }, [getThemeTokensBase]);
289
+ const getFocusBorderTokens = (0, _componentsBase.useThemeTokensCallback)('Card', {}, {
135
290
  ...variant,
136
291
  interactive: true
137
- }).borderWidth;
138
- const marginOffset = `${-(cardBaseBorderWidth + pressableBorderWidth) / 2}px`;
139
- const getThemeTokens = (0, _componentsBase.useThemeTokensCallback)('Card', interactiveCard?.tokens, {
140
- interactive: true,
141
- ...(interactiveCard?.variant || {})
142
292
  });
143
- const {
144
- backgroundColor: _,
145
- ...tokensWithoutBg
146
- } = tokens;
147
- const getFullBleedInteractiveTokens = (0, _componentsBase.useThemeTokensCallback)('Card', tokensWithoutBg, {
293
+
294
+ // Keep backgroundColor for CardContent, it won't affect FullBleedContent image
295
+ const tokensWithoutBg = tokens;
296
+ const fullBleedInteractiveVariant = backgroundImage ? {
297
+ ...variant,
298
+ interactive: true,
299
+ style: undefined
300
+ } : {
148
301
  ...variant,
149
302
  interactive: true
150
- });
151
- const getFullBleedInteractiveCardTokens = cardState => ({
152
- ...getFullBleedInteractiveTokens(cardState),
153
- paddingTop: 0,
154
- paddingBottom: 0,
155
- paddingLeft: 0,
156
- paddingRight: 0,
157
- // Suppress gradient if interactiveCard.body exists to avoid border duplication
158
- ...(interactiveCard?.body ? {
159
- gradient: undefined
160
- } : {})
161
- });
303
+ };
304
+ const getFullBleedInteractiveTokens = (0, _componentsBase.useThemeTokensCallback)('Card', tokensWithoutBg, fullBleedInteractiveVariant);
305
+ const getFullBleedInteractiveCardTokens = cardState => {
306
+ return {
307
+ ...getFullBleedInteractiveTokens(cardState),
308
+ paddingTop: 0,
309
+ paddingBottom: 0,
310
+ paddingLeft: 0,
311
+ paddingRight: 0,
312
+ borderWidth: 0,
313
+ ...(interactiveCard?.body ? {
314
+ gradient: undefined
315
+ } : {})
316
+ };
317
+ };
162
318
  const hasFooter = Boolean(footer);
163
319
  const fullBleedBorderRadius = (0, _FullBleedContent.getFullBleedBorderRadius)(borderRadius, fullBleedContentPosition, hasFooter);
164
320
 
@@ -167,12 +323,15 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
167
323
  // pass as props to ConditionalWrapper
168
324
  const imgColCurrentViewport = (0, _componentsBase.useResponsiveProp)(imgCol);
169
325
  const maxCol = GRID_COLUMNS;
170
- const fullBleedImageWidth = `${imgColCurrentViewport / maxCol * 100}%`;
171
- const adaptiveContentWidth = `${(maxCol - imgColCurrentViewport) / maxCol * 100}%`;
172
- const isImageWidthAdjustable = imgCol && (fullBleedContentPosition === 'left' || fullBleedContentPosition === 'right');
326
+ const hasValidImgCol = imgCol && imgColCurrentViewport !== undefined && !Number.isNaN(imgColCurrentViewport);
327
+ const fullBleedImageWidth = hasValidImgCol ? `${imgColCurrentViewport / maxCol * 100}%` : undefined;
328
+ const adaptiveContentWidth = hasValidImgCol ? `${(maxCol - imgColCurrentViewport) / maxCol * 100}%` : undefined;
329
+ const isImageWidthAdjustable = hasValidImgCol && (fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT);
173
330
  const contentWrapperStyleProps = {
174
- width: adaptiveContentWidth,
175
- ...(imgColCurrentViewport >= maxCol && {
331
+ ...(hasValidImgCol && {
332
+ width: adaptiveContentWidth
333
+ }),
334
+ ...(hasValidImgCol && imgColCurrentViewport >= maxCol && {
176
335
  display: 'none'
177
336
  }),
178
337
  ...(fullBleedContentChildrenAlign && {
@@ -184,26 +343,35 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
184
343
  flexShrink: 1,
185
344
  justifyContent: 'space-between'
186
345
  };
187
- const cardBaseTokens = Object.fromEntries(Object.entries(tokens).filter(_ref2 => {
188
- let [key] = _ref2;
189
- return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage ? ['backgroundColor'] : [])].includes(key);
346
+ const cardBaseTokens = Object.fromEntries(Object.entries(tokens).filter(_ref4 => {
347
+ let [key] = _ref4;
348
+ return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage ? ['backgroundColor', 'gradient', 'backgroundGradient'] : [])].includes(key);
190
349
  }));
350
+ const cardBaseVariant = backgroundImage ? {
351
+ ...(interactiveCard?.body ? mergedVariant : variant),
352
+ padding: 'custom',
353
+ style: undefined
354
+ } : {
355
+ ...(interactiveCard?.body ? mergedVariant : variant),
356
+ padding: 'custom'
357
+ };
358
+ const isHorizontalFullBleed = fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT;
359
+ const isVerticalFullBleed = fullBleedContentPosition === POSITION.TOP || fullBleedContentPosition === POSITION.BOTTOM;
191
360
  const imageWrapperStyleProps = {
192
- width: fullBleedImageWidth,
193
- ...(imgColCurrentViewport >= maxCol && {
361
+ ...(isImageWidthAdjustable && {
362
+ width: fullBleedImageWidth
363
+ }),
364
+ ...(isImageWidthAdjustable && imgColCurrentViewport >= maxCol && {
194
365
  borderRadius,
195
366
  overflow: 'hidden'
196
367
  }),
197
- ...(imgColCurrentViewport === 0 && {
368
+ ...(isImageWidthAdjustable && imgColCurrentViewport === 0 && {
198
369
  display: 'none'
199
370
  })
200
371
  };
201
372
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.Card, {
202
373
  ref: ref,
203
- variant: {
204
- ...variant,
205
- padding: 'custom'
206
- },
374
+ variant: cardBaseVariant,
207
375
  tokens: cardBaseTokens,
208
376
  backgroundImage: backgroundImage,
209
377
  onPress: fullBleedInteractive ? undefined : onPress,
@@ -213,9 +381,12 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
213
381
  }),
214
382
  ...selectProps(restProps),
215
383
  children: [interactiveCard?.selectionType && children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
216
- tokens: tokens,
384
+ tokens: getCardContentTokens(tokens, {
385
+ backgroundImage
386
+ }),
217
387
  variant: variant,
218
388
  withFooter: hasFooter,
389
+ backgroundImage: backgroundImage,
219
390
  children: children
220
391
  }) : null, interactiveCard?.body && !interactiveCard.selectionType ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
221
392
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.PressableCardBase, {
@@ -229,104 +400,110 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
229
400
  children: cardState => /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
230
401
  children: typeof interactiveCard?.body === 'function' ? interactiveCard.body(cardState) : interactiveCard.body
231
402
  })
232
- }), children && fullBleedContentPosition === 'none' && !fullBleedInteractive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
233
- tokens: tokens,
403
+ }), children && fullBleedContentPosition === POSITION.NONE && !fullBleedInteractive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
404
+ tokens: getCardContentTokens(tokens, {
405
+ backgroundImage
406
+ }),
234
407
  variant: variant,
235
408
  withFooter: hasFooter,
409
+ backgroundImage: backgroundImage,
236
410
  children: children
237
411
  }) : null]
238
- }) : null, fullBleedInteractive ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
239
- style: {
240
- marginTop: marginOffset,
241
- marginBottom: marginOffset,
242
- marginLeft: marginOffset,
243
- marginRight: marginOffset
244
- },
245
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.PressableCardBase, {
246
- ref: ref,
247
- tokens: getFullBleedInteractiveCardTokens,
248
- dataSet: dataSet,
249
- onPress: effectiveFullBleedOnPress,
250
- href: effectiveFullBleedHref,
251
- hrefAttrs: effectiveFullBleedHrefAttrs,
252
- ...selectProps(restProps),
253
- children: cardState => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.StackView, {
254
- direction: contentStackDirection,
255
- tokens: {
256
- ...columnFlex,
257
- alignItems: contentStackAlign
258
- },
259
- space: 0,
260
- children: [children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
261
- WrapperComponent: DynamicWidthContainer,
262
- wrapperProps: contentWrapperStyleProps,
263
- condition: isImageWidthAdjustable,
264
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
265
- tokens: {
266
- ...tokensWithoutBg,
267
- ...(backgroundImage ? {} : {
268
- backgroundColor: 'transparent'
269
- }),
270
- ...(!isImageWidthAdjustable && fullBleedContentChildrenAlign && {
271
- alignSelf: fullBleedContentChildrenAlign
272
- })
273
- },
274
- variant: variant,
275
- withFooter: hasFooter,
276
- children: children
277
- })
278
- }) : null, fullBleedContentPosition !== 'none' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
279
- WrapperComponent: DynamicWidthContainer,
280
- wrapperProps: imageWrapperStyleProps,
281
- condition: isImageWidthAdjustable,
282
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FullBleedContent.default, {
283
- borderRadius: fullBleedBorderRadius,
284
- ...fullBleedContentPropsClean,
285
- position: fullBleedContentPosition,
286
- cardState: cardState
287
- })
412
+ }) : null, fullBleedInteractive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.PressableCardBase, {
413
+ ref: ref,
414
+ tokens: getFullBleedInteractiveCardTokens,
415
+ dataSet: dataSet,
416
+ onPress: effectiveFullBleedOnPress,
417
+ href: effectiveFullBleedHref,
418
+ hrefAttrs: effectiveFullBleedHrefAttrs,
419
+ ...selectProps(restProps),
420
+ children: cardState => {
421
+ let overlayOpacity = 0;
422
+ if (cardState.pressed) {
423
+ overlayOpacity = 0.2;
424
+ } else if (cardState.hover) {
425
+ overlayOpacity = 0.1;
426
+ }
427
+ const focusTokens = getFocusBorderTokens(cardState);
428
+ const showFocusBorder = cardState.focus && focusTokens.borderWidth > 0;
429
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(InteractiveCardWrapper, {
430
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.StackView, {
431
+ direction: contentStackDirection,
432
+ tokens: getStackViewTokens(columnFlex, contentStackAlign),
433
+ space: 0,
434
+ children: [children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
435
+ WrapperComponent: DynamicWidthContainer,
436
+ wrapperProps: contentWrapperStyleProps,
437
+ condition: isImageWidthAdjustable,
438
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
439
+ tokens: {
440
+ ...getCardContentTokens(tokensWithoutBg, {
441
+ backgroundImage,
442
+ fullBleedContentChildrenAlign,
443
+ useTransparentBackground: true
444
+ }),
445
+ paddingTop: tokens.paddingTop !== undefined ? tokens.paddingTop : allThemeTokens.paddingTop,
446
+ paddingBottom: tokens.paddingBottom !== undefined ? tokens.paddingBottom : allThemeTokens.paddingBottom,
447
+ paddingLeft: tokens.paddingLeft !== undefined ? tokens.paddingLeft : allThemeTokens.paddingLeft,
448
+ paddingRight: tokens.paddingRight !== undefined ? tokens.paddingRight : allThemeTokens.paddingRight
449
+ },
450
+ variant: variant,
451
+ withFooter: hasFooter,
452
+ backgroundImage: backgroundImage,
453
+ children: children
454
+ })
455
+ }) : null, fullBleedContentPosition !== POSITION.NONE && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
456
+ WrapperComponent: DynamicWidthContainer,
457
+ wrapperProps: imageWrapperStyleProps,
458
+ condition: isImageWidthAdjustable || isHorizontalFullBleed || isVerticalFullBleed,
459
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FullBleedContent.default, {
460
+ borderRadius: fullBleedBorderRadius,
461
+ ...fullBleedContentPropsClean,
462
+ position: fullBleedContentPosition,
463
+ cardState: undefined
464
+ })
465
+ })]
466
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(InteractiveOverlay, {
467
+ overlayOpacity: overlayOpacity,
468
+ borderRadius: borderRadius
469
+ }), showFocusBorder && /*#__PURE__*/(0, _jsxRuntime.jsx)(FocusBorder, {
470
+ borderWidth: `${focusTokens.borderWidth}px`,
471
+ borderColor: focusTokens.borderColor,
472
+ borderRadius: borderRadius
288
473
  })]
289
- })
290
- })
291
- }) : null, !fullBleedInteractive && !interactiveCard?.body && fullBleedContentPosition === 'none' && children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
292
- tokens: {
293
- ...tokens,
294
- ...(backgroundImage ? {
295
- backgroundColor: 'transparent'
296
- } : {}),
297
- ...(fullBleedContentChildrenAlign && {
298
- alignSelf: fullBleedContentChildrenAlign
299
- })
300
- },
474
+ });
475
+ }
476
+ }) : null, !fullBleedInteractive && !interactiveCard?.body && fullBleedContentPosition === POSITION.NONE && children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
477
+ tokens: getCardContentTokens(tokens, {
478
+ backgroundImage,
479
+ fullBleedContentChildrenAlign
480
+ }),
301
481
  variant: variant,
302
482
  withFooter: hasFooter,
483
+ backgroundImage: backgroundImage,
303
484
  children: children
304
- }) : null, !fullBleedInteractive && fullBleedContentPosition !== 'none' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.StackView, {
485
+ }) : null, !fullBleedInteractive && fullBleedContentPosition !== POSITION.NONE ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.StackView, {
305
486
  direction: contentStackDirection,
306
- tokens: {
307
- ...columnFlex,
308
- alignItems: contentStackAlign
309
- },
487
+ tokens: getStackViewTokens(columnFlex, contentStackAlign),
310
488
  space: 0,
311
489
  children: [children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
312
490
  WrapperComponent: DynamicWidthContainer,
313
491
  wrapperProps: contentWrapperStyleProps,
314
492
  condition: isImageWidthAdjustable,
315
493
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
316
- tokens: {
317
- ...tokens,
318
- ...(!isImageWidthAdjustable && fullBleedContentChildrenAlign && {
319
- alignSelf: fullBleedContentChildrenAlign
320
- })
321
- },
494
+ tokens: getCardContentTokens(tokens, {
495
+ backgroundImage,
496
+ fullBleedContentChildrenAlign
497
+ }),
322
498
  variant: variant,
323
499
  withFooter: hasFooter,
500
+ backgroundImage: backgroundImage,
324
501
  children: children
325
502
  })
326
503
  }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
327
504
  WrapperComponent: DynamicWidthContainer,
328
505
  wrapperProps: imageWrapperStyleProps,
329
- condition: isImageWidthAdjustable,
506
+ condition: isImageWidthAdjustable || isHorizontalFullBleed || isVerticalFullBleed,
330
507
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FullBleedContent.default, {
331
508
  borderRadius: fullBleedBorderRadius,
332
509
  ...fullBleedContentPropsClean,
@@ -342,7 +519,7 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
342
519
  })]
343
520
  });
344
521
  });
345
- const positionValues = ['none', 'bottom', 'left', 'right', 'top'];
522
+ const positionValues = Object.values(POSITION);
346
523
  const alignValues = ['start', 'end', 'center', 'stretch'];
347
524
  const PositionedFullBleedContentPropType = _propTypes.default.shape({
348
525
  position: _componentsBase.responsiveProps.getTypeOptionallyByViewport(_propTypes.default.oneOf(positionValues)).isRequired,
@@ -63,6 +63,7 @@ const CardContent = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
63
63
  tokens,
64
64
  variant,
65
65
  withFooter = false,
66
+ backgroundImage,
66
67
  ...rest
67
68
  } = _ref2;
68
69
  const {
@@ -71,10 +72,32 @@ const CardContent = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
71
72
  }
72
73
  } = (0, _componentsBase.useTheme)();
73
74
  const allTokens = (0, _componentsBase.useAllViewportTokens)('Card', tokens, variant);
75
+
76
+ // Override backgroundColor if explicitly set in tokens to ensure it takes priority over theme tokens
77
+ // This is crucial for scenarios with backgroundImage where we need transparency
78
+ if (tokens.backgroundColor !== undefined) {
79
+ allTokens.current.backgroundColor = tokens.backgroundColor;
80
+ allTokens.xs.backgroundColor = tokens.backgroundColor;
81
+ allTokens.sm.backgroundColor = tokens.backgroundColor;
82
+ allTokens.md.backgroundColor = tokens.backgroundColor;
83
+ allTokens.lg.backgroundColor = tokens.backgroundColor;
84
+ allTokens.xl.backgroundColor = tokens.backgroundColor;
85
+ }
86
+
87
+ // When backgroundImage is present on the Card, ensure CardContent background is transparent
88
+ // so the background image from the parent CardBase can show through
89
+ if (backgroundImage) {
90
+ allTokens.current.backgroundColor = 'transparent';
91
+ allTokens.xs.backgroundColor = 'transparent';
92
+ allTokens.sm.backgroundColor = 'transparent';
93
+ allTokens.md.backgroundColor = 'transparent';
94
+ allTokens.lg.backgroundColor = 'transparent';
95
+ allTokens.xl.backgroundColor = 'transparent';
96
+ }
74
97
  let themeTokens;
75
98
  let mediaIds;
76
99
  if (enableMediaQueryStyleSheet) {
77
- const stylesByViewport = {
100
+ const paddingAdjustments = {
78
101
  xs: {
79
102
  paddingBottom: allTokens.xs.paddingBottom - allTokens.xs.borderWidth,
80
103
  paddingLeft: allTokens.xs.paddingLeft - allTokens.xs.borderWidth,
@@ -106,15 +129,16 @@ const CardContent = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
106
129
  paddingTop: allTokens.xl.paddingTop - allTokens.xl.borderWidth
107
130
  }
108
131
  };
109
- const mediaQueryStyles = (0, _componentsBase.createMediaQueryStyles)(stylesByViewport);
132
+ const mediaQueryStyles = (0, _componentsBase.createMediaQueryStyles)(paddingAdjustments);
133
+ const baseStyle = {
134
+ ...allTokens.current,
135
+ ...mediaQueryStyles
136
+ };
110
137
  const {
111
138
  ids,
112
139
  styles
113
140
  } = _componentsBase.StyleSheet.create({
114
- cardContent: {
115
- ...allTokens.current,
116
- ...mediaQueryStyles
117
- }
141
+ cardContent: baseStyle
118
142
  });
119
143
  themeTokens = styles.cardContent;
120
144
  mediaIds = ids.cardContent;
@@ -152,6 +176,11 @@ CardContent.propTypes = {
152
176
  /**
153
177
  * Whether the card has a footer.
154
178
  */
155
- withFooter: _propTypes.default.bool
179
+ withFooter: _propTypes.default.bool,
180
+ /**
181
+ * Background image object from parent Card component.
182
+ * When present, makes the CardContent background transparent.
183
+ */
184
+ backgroundImage: _propTypes.default.object
156
185
  };
157
186
  var _default = exports.default = CardContent;