@telus-uds/components-web 4.17.0 → 4.18.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.
@@ -11,6 +11,63 @@ import ConditionalWrapper from '../shared/ConditionalWrapper';
11
11
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
13
13
  const GRID_COLUMNS = 12;
14
+ const POSITION = {
15
+ LEFT: 'left',
16
+ RIGHT: 'right',
17
+ TOP: 'top',
18
+ BOTTOM: 'bottom',
19
+ NONE: 'none'
20
+ };
21
+
22
+ /**
23
+ * Helper function to get StackView tokens
24
+ * @param {Object} columnFlex - Column flex properties
25
+ * @param {string} contentStackAlign - Alignment value for content stack
26
+ * @returns {Object} StackView tokens object
27
+ */
28
+ const getStackViewTokens = (columnFlex, contentStackAlign) => ({
29
+ ...columnFlex,
30
+ alignItems: contentStackAlign
31
+ });
32
+
33
+ /**
34
+ * Helper function to get CardContent tokens
35
+ * @param {Object} baseTokens - Base tokens to spread
36
+ * @param {Object} options - Options object
37
+ * @param {boolean} options.backgroundImage - Whether background image is present
38
+ * @param {string} options.fullBleedContentChildrenAlign - Alignment for full bleed content children
39
+ * @param {boolean} options.useTransparentBackground - Whether to use transparent background when no backgroundImage
40
+ * @returns {Object} CardContent tokens object
41
+ */
42
+ const getCardContentTokens = function (baseTokens) {
43
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
44
+ const {
45
+ backgroundImage,
46
+ fullBleedContentChildrenAlign,
47
+ useTransparentBackground
48
+ } = options;
49
+
50
+ // Determine background color based on conditions
51
+ let backgroundColorOverride = {};
52
+ if (useTransparentBackground) {
53
+ if (!backgroundImage) {
54
+ backgroundColorOverride = {
55
+ backgroundColor: 'transparent'
56
+ };
57
+ }
58
+ } else if (backgroundImage) {
59
+ backgroundColorOverride = {
60
+ backgroundColor: 'transparent'
61
+ };
62
+ }
63
+ return {
64
+ ...baseTokens,
65
+ ...backgroundColorOverride,
66
+ ...(fullBleedContentChildrenAlign && {
67
+ alignSelf: fullBleedContentChildrenAlign
68
+ })
69
+ };
70
+ };
14
71
 
15
72
  /**
16
73
  * A basic card component, unstyled by default.
@@ -69,6 +126,59 @@ const DynamicWidthContainer = /*#__PURE__*/styled.div.withConfig({
69
126
  alignSelf
70
127
  };
71
128
  });
129
+ const InteractiveCardWrapper = /*#__PURE__*/styled.div.withConfig({
130
+ displayName: "Card__InteractiveCardWrapper",
131
+ componentId: "components-web__sc-1elbtwd-1"
132
+ })(() => ({
133
+ position: 'relative',
134
+ flex: 1,
135
+ display: 'flex',
136
+ flexDirection: 'column'
137
+ }));
138
+ const InteractiveOverlay = /*#__PURE__*/styled.div.withConfig({
139
+ displayName: "Card__InteractiveOverlay",
140
+ componentId: "components-web__sc-1elbtwd-2"
141
+ })(_ref2 => {
142
+ let {
143
+ overlayOpacity,
144
+ borderRadius
145
+ } = _ref2;
146
+ return {
147
+ position: 'absolute',
148
+ top: 0,
149
+ left: 0,
150
+ right: 0,
151
+ bottom: 0,
152
+ backgroundColor: `rgba(0, 0, 0, ${overlayOpacity || 0})`,
153
+ borderRadius,
154
+ pointerEvents: 'none',
155
+ transition: 'background-color 0.2s ease',
156
+ zIndex: 1
157
+ };
158
+ });
159
+ const FocusBorder = /*#__PURE__*/styled.div.withConfig({
160
+ displayName: "Card__FocusBorder",
161
+ componentId: "components-web__sc-1elbtwd-3"
162
+ })(_ref3 => {
163
+ let {
164
+ borderWidth,
165
+ borderColor,
166
+ borderRadius
167
+ } = _ref3;
168
+ return {
169
+ position: 'absolute',
170
+ top: 0,
171
+ left: 0,
172
+ right: 0,
173
+ bottom: 0,
174
+ borderWidth,
175
+ borderColor,
176
+ borderRadius,
177
+ borderStyle: 'solid',
178
+ pointerEvents: 'none',
179
+ zIndex: 2
180
+ };
181
+ });
72
182
  const Card = /*#__PURE__*/React.forwardRef(function () {
73
183
  let {
74
184
  children,
@@ -122,16 +232,57 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
122
232
  const {
123
233
  borderRadius
124
234
  } = allThemeTokens;
125
- const cardBaseBorderWidth = allThemeTokens.borderWidth;
126
- const pressableBorderWidth = useThemeTokens('Card', {}, {
235
+
236
+ // Interactive cards: merge variants for CardBase (outer container)
237
+ // The outer variant takes priority over interactiveCard.variant for the style property
238
+ // This ensures the gradient is only applied to CardBase, not PressableCardBase and avoid duplication
239
+ const interactiveStyle = interactiveCard?.variant?.style;
240
+ const outerStyle = variant?.style;
241
+ const mergedVariant = {
242
+ ...variant,
243
+ style: outerStyle || interactiveStyle
244
+ };
245
+
246
+ // Interactive cards: build configuration for PressableCardBase
247
+ // This determines which style to use for interactive states (hover, pressed, etc.)
248
+ // without causing gradient duplication
249
+ let interactiveCardConfig = {};
250
+ if (interactiveCard?.body) {
251
+ const styleToUse = interactiveCard?.variant?.style || variant?.style;
252
+ const {
253
+ style,
254
+ ...otherVariantProps
255
+ } = interactiveCard?.variant || {};
256
+ interactiveCardConfig = {
257
+ interactive: true,
258
+ ...(styleToUse && {
259
+ style: styleToUse
260
+ }),
261
+ ...otherVariantProps
262
+ };
263
+ }
264
+ const getThemeTokensBase = useThemeTokensCallback('Card', interactiveCard?.tokens, interactiveCardConfig);
265
+
266
+ // Wrap getThemeTokens to remove gradient from resolved tokens
267
+ // PressableCardBase calls this function with pressableState (hover, pressed, etc.)
268
+ // We intercept the resolved tokens and remove gradient properties to prevent duplication
269
+ // since the gradient should only appear on CardBase (outer container)
270
+ const getThemeTokens = React.useCallback(pressableState => {
271
+ const resolvedTokens = getThemeTokensBase(pressableState);
272
+ const {
273
+ gradient,
274
+ backgroundGradient,
275
+ ...tokensWithoutGradient
276
+ } = resolvedTokens;
277
+ return tokensWithoutGradient;
278
+ }, [getThemeTokensBase]);
279
+ const getFocusBorderTokens = useThemeTokensCallback('Card', {}, {
127
280
  ...variant,
128
281
  interactive: true
129
- }).borderWidth;
130
- const marginOffset = `${-(cardBaseBorderWidth + pressableBorderWidth) / 2}px`;
131
- const getThemeTokens = useThemeTokensCallback('Card', interactiveCard?.tokens, {
132
- interactive: true,
133
- ...(interactiveCard?.variant || {})
134
282
  });
283
+
284
+ // Remove backgroundColor from tokens for full bleed interactive content
285
+ // to prevent background from covering the full bleed image
135
286
  const {
136
287
  backgroundColor: _,
137
288
  ...tokensWithoutBg
@@ -140,17 +291,19 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
140
291
  ...variant,
141
292
  interactive: true
142
293
  });
143
- const getFullBleedInteractiveCardTokens = cardState => ({
144
- ...getFullBleedInteractiveTokens(cardState),
145
- paddingTop: 0,
146
- paddingBottom: 0,
147
- paddingLeft: 0,
148
- paddingRight: 0,
149
- // Suppress gradient if interactiveCard.body exists to avoid border duplication
150
- ...(interactiveCard?.body ? {
151
- gradient: undefined
152
- } : {})
153
- });
294
+ const getFullBleedInteractiveCardTokens = cardState => {
295
+ return {
296
+ ...getFullBleedInteractiveTokens(cardState),
297
+ paddingTop: 0,
298
+ paddingBottom: 0,
299
+ paddingLeft: 0,
300
+ paddingRight: 0,
301
+ borderWidth: 0,
302
+ ...(interactiveCard?.body ? {
303
+ gradient: undefined
304
+ } : {})
305
+ };
306
+ };
154
307
  const hasFooter = Boolean(footer);
155
308
  const fullBleedBorderRadius = getFullBleedBorderRadius(borderRadius, fullBleedContentPosition, hasFooter);
156
309
 
@@ -159,12 +312,15 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
159
312
  // pass as props to ConditionalWrapper
160
313
  const imgColCurrentViewport = useResponsiveProp(imgCol);
161
314
  const maxCol = GRID_COLUMNS;
162
- const fullBleedImageWidth = `${imgColCurrentViewport / maxCol * 100}%`;
163
- const adaptiveContentWidth = `${(maxCol - imgColCurrentViewport) / maxCol * 100}%`;
164
- const isImageWidthAdjustable = imgCol && (fullBleedContentPosition === 'left' || fullBleedContentPosition === 'right');
315
+ const hasValidImgCol = imgCol && imgColCurrentViewport !== undefined && !Number.isNaN(imgColCurrentViewport);
316
+ const fullBleedImageWidth = hasValidImgCol ? `${imgColCurrentViewport / maxCol * 100}%` : undefined;
317
+ const adaptiveContentWidth = hasValidImgCol ? `${(maxCol - imgColCurrentViewport) / maxCol * 100}%` : undefined;
318
+ const isImageWidthAdjustable = hasValidImgCol && (fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT);
165
319
  const contentWrapperStyleProps = {
166
- width: adaptiveContentWidth,
167
- ...(imgColCurrentViewport >= maxCol && {
320
+ ...(hasValidImgCol && {
321
+ width: adaptiveContentWidth
322
+ }),
323
+ ...(hasValidImgCol && imgColCurrentViewport >= maxCol && {
168
324
  display: 'none'
169
325
  }),
170
326
  ...(fullBleedContentChildrenAlign && {
@@ -176,28 +332,32 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
176
332
  flexShrink: 1,
177
333
  justifyContent: 'space-between'
178
334
  };
179
- const cardBaseTokens = Object.fromEntries(Object.entries(tokens).filter(_ref2 => {
180
- let [key] = _ref2;
181
- return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage ? ['backgroundColor'] : [])].includes(key);
335
+ const cardBaseTokens = Object.fromEntries(Object.entries(tokens).filter(_ref4 => {
336
+ let [key] = _ref4;
337
+ return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage && interactiveCard?.body ? ['backgroundColor'] : [])].includes(key);
182
338
  }));
339
+ const isHorizontalFullBleed = fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT;
340
+ const isVerticalFullBleed = fullBleedContentPosition === POSITION.TOP || fullBleedContentPosition === POSITION.BOTTOM;
183
341
  const imageWrapperStyleProps = {
184
- width: fullBleedImageWidth,
185
- ...(imgColCurrentViewport >= maxCol && {
342
+ ...(isImageWidthAdjustable && {
343
+ width: fullBleedImageWidth
344
+ }),
345
+ ...(isImageWidthAdjustable && imgColCurrentViewport >= maxCol && {
186
346
  borderRadius,
187
347
  overflow: 'hidden'
188
348
  }),
189
- ...(imgColCurrentViewport === 0 && {
349
+ ...(isImageWidthAdjustable && imgColCurrentViewport === 0 && {
190
350
  display: 'none'
191
351
  })
192
352
  };
193
353
  return /*#__PURE__*/_jsxs(CardBase, {
194
354
  ref: ref,
195
355
  variant: {
196
- ...variant,
356
+ ...(interactiveCard?.body ? mergedVariant : variant),
197
357
  padding: 'custom'
198
358
  },
199
359
  tokens: cardBaseTokens,
200
- backgroundImage: backgroundImage,
360
+ backgroundImage: !interactiveCard?.body && backgroundImage,
201
361
  onPress: fullBleedInteractive ? undefined : onPress,
202
362
  ...(interactiveCard?.selectionType && {
203
363
  interactiveCard,
@@ -214,6 +374,7 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
214
374
  ref: ref,
215
375
  tokens: getThemeTokens,
216
376
  dataSet: dataSet,
377
+ backgroundImage: backgroundImage,
217
378
  onPress: onPress,
218
379
  href: interactiveCard?.href,
219
380
  hrefAttrs: interactiveCard?.hrefAttrs,
@@ -221,96 +382,95 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
221
382
  children: cardState => /*#__PURE__*/_jsx(_Fragment, {
222
383
  children: typeof interactiveCard?.body === 'function' ? interactiveCard.body(cardState) : interactiveCard.body
223
384
  })
224
- }), children && fullBleedContentPosition === 'none' && !fullBleedInteractive ? /*#__PURE__*/_jsx(CardContent, {
385
+ }), children && fullBleedContentPosition === POSITION.NONE && !fullBleedInteractive ? /*#__PURE__*/_jsx(CardContent, {
225
386
  tokens: tokens,
226
387
  variant: variant,
227
388
  withFooter: hasFooter,
228
389
  children: children
229
390
  }) : null]
230
- }) : null, fullBleedInteractive ? /*#__PURE__*/_jsx("div", {
231
- style: {
232
- marginTop: marginOffset,
233
- marginBottom: marginOffset,
234
- marginLeft: marginOffset,
235
- marginRight: marginOffset
236
- },
237
- children: /*#__PURE__*/_jsx(PressableCardBase, {
238
- ref: ref,
239
- tokens: getFullBleedInteractiveCardTokens,
240
- dataSet: dataSet,
241
- onPress: effectiveFullBleedOnPress,
242
- href: effectiveFullBleedHref,
243
- hrefAttrs: effectiveFullBleedHrefAttrs,
244
- ...selectProps(restProps),
245
- children: cardState => /*#__PURE__*/_jsxs(StackView, {
246
- direction: contentStackDirection,
247
- tokens: {
248
- ...columnFlex,
249
- alignItems: contentStackAlign
250
- },
251
- space: 0,
252
- children: [children ? /*#__PURE__*/_jsx(ConditionalWrapper, {
253
- WrapperComponent: DynamicWidthContainer,
254
- wrapperProps: contentWrapperStyleProps,
255
- condition: isImageWidthAdjustable,
256
- children: /*#__PURE__*/_jsx(CardContent, {
257
- tokens: {
258
- ...tokensWithoutBg,
259
- ...(backgroundImage ? {} : {
260
- backgroundColor: 'transparent'
261
- }),
262
- ...(!isImageWidthAdjustable && fullBleedContentChildrenAlign && {
263
- alignSelf: fullBleedContentChildrenAlign
264
- })
265
- },
266
- variant: variant,
267
- withFooter: hasFooter,
268
- children: children
269
- })
270
- }) : null, fullBleedContentPosition !== 'none' && /*#__PURE__*/_jsx(ConditionalWrapper, {
271
- WrapperComponent: DynamicWidthContainer,
272
- wrapperProps: imageWrapperStyleProps,
273
- condition: isImageWidthAdjustable,
274
- children: /*#__PURE__*/_jsx(FullBleedContent, {
275
- borderRadius: fullBleedBorderRadius,
276
- ...fullBleedContentPropsClean,
277
- position: fullBleedContentPosition,
278
- cardState: cardState
279
- })
391
+ }) : null, fullBleedInteractive ? /*#__PURE__*/_jsx(PressableCardBase, {
392
+ ref: ref,
393
+ tokens: getFullBleedInteractiveCardTokens,
394
+ dataSet: dataSet,
395
+ onPress: effectiveFullBleedOnPress,
396
+ href: effectiveFullBleedHref,
397
+ hrefAttrs: effectiveFullBleedHrefAttrs,
398
+ ...selectProps(restProps),
399
+ children: cardState => {
400
+ let overlayOpacity = 0;
401
+ if (cardState.pressed) {
402
+ overlayOpacity = 0.2;
403
+ } else if (cardState.hover) {
404
+ overlayOpacity = 0.1;
405
+ }
406
+ const focusTokens = getFocusBorderTokens(cardState);
407
+ const showFocusBorder = cardState.focus && focusTokens.borderWidth > 0;
408
+ return /*#__PURE__*/_jsxs(InteractiveCardWrapper, {
409
+ children: [/*#__PURE__*/_jsxs(StackView, {
410
+ direction: contentStackDirection,
411
+ tokens: getStackViewTokens(columnFlex, contentStackAlign),
412
+ space: 0,
413
+ children: [children ? /*#__PURE__*/_jsx(ConditionalWrapper, {
414
+ WrapperComponent: DynamicWidthContainer,
415
+ wrapperProps: contentWrapperStyleProps,
416
+ condition: isImageWidthAdjustable,
417
+ children: /*#__PURE__*/_jsx(CardContent, {
418
+ tokens: {
419
+ ...getCardContentTokens(tokensWithoutBg, {
420
+ backgroundImage,
421
+ fullBleedContentChildrenAlign,
422
+ useTransparentBackground: true
423
+ }),
424
+ paddingTop: tokens.paddingTop !== undefined ? tokens.paddingTop : allThemeTokens.paddingTop,
425
+ paddingBottom: tokens.paddingBottom !== undefined ? tokens.paddingBottom : allThemeTokens.paddingBottom,
426
+ paddingLeft: tokens.paddingLeft !== undefined ? tokens.paddingLeft : allThemeTokens.paddingLeft,
427
+ paddingRight: tokens.paddingRight !== undefined ? tokens.paddingRight : allThemeTokens.paddingRight
428
+ },
429
+ variant: variant,
430
+ withFooter: hasFooter,
431
+ children: children
432
+ })
433
+ }) : null, fullBleedContentPosition !== POSITION.NONE && /*#__PURE__*/_jsx(ConditionalWrapper, {
434
+ WrapperComponent: DynamicWidthContainer,
435
+ wrapperProps: imageWrapperStyleProps,
436
+ condition: isImageWidthAdjustable || isHorizontalFullBleed || isVerticalFullBleed,
437
+ children: /*#__PURE__*/_jsx(FullBleedContent, {
438
+ borderRadius: fullBleedBorderRadius,
439
+ ...fullBleedContentPropsClean,
440
+ position: fullBleedContentPosition,
441
+ cardState: undefined
442
+ })
443
+ })]
444
+ }), /*#__PURE__*/_jsx(InteractiveOverlay, {
445
+ overlayOpacity: overlayOpacity,
446
+ borderRadius: borderRadius
447
+ }), showFocusBorder && /*#__PURE__*/_jsx(FocusBorder, {
448
+ borderWidth: `${focusTokens.borderWidth}px`,
449
+ borderColor: focusTokens.borderColor,
450
+ borderRadius: borderRadius
280
451
  })]
281
- })
282
- })
283
- }) : null, !fullBleedInteractive && !interactiveCard?.body && fullBleedContentPosition === 'none' && children ? /*#__PURE__*/_jsx(CardContent, {
284
- tokens: {
285
- ...tokens,
286
- ...(backgroundImage ? {
287
- backgroundColor: 'transparent'
288
- } : {}),
289
- ...(fullBleedContentChildrenAlign && {
290
- alignSelf: fullBleedContentChildrenAlign
291
- })
292
- },
452
+ });
453
+ }
454
+ }) : null, !fullBleedInteractive && !interactiveCard?.body && fullBleedContentPosition === POSITION.NONE && children ? /*#__PURE__*/_jsx(CardContent, {
455
+ tokens: getCardContentTokens(tokens, {
456
+ backgroundImage,
457
+ fullBleedContentChildrenAlign
458
+ }),
293
459
  variant: variant,
294
460
  withFooter: hasFooter,
295
461
  children: children
296
- }) : null, !fullBleedInteractive && fullBleedContentPosition !== 'none' ? /*#__PURE__*/_jsxs(StackView, {
462
+ }) : null, !fullBleedInteractive && fullBleedContentPosition !== POSITION.NONE ? /*#__PURE__*/_jsxs(StackView, {
297
463
  direction: contentStackDirection,
298
- tokens: {
299
- ...columnFlex,
300
- alignItems: contentStackAlign
301
- },
464
+ tokens: getStackViewTokens(columnFlex, contentStackAlign),
302
465
  space: 0,
303
466
  children: [children ? /*#__PURE__*/_jsx(ConditionalWrapper, {
304
467
  WrapperComponent: DynamicWidthContainer,
305
468
  wrapperProps: contentWrapperStyleProps,
306
469
  condition: isImageWidthAdjustable,
307
470
  children: /*#__PURE__*/_jsx(CardContent, {
308
- tokens: {
309
- ...tokens,
310
- ...(!isImageWidthAdjustable && fullBleedContentChildrenAlign && {
311
- alignSelf: fullBleedContentChildrenAlign
312
- })
313
- },
471
+ tokens: getCardContentTokens(tokens, {
472
+ fullBleedContentChildrenAlign
473
+ }),
314
474
  variant: variant,
315
475
  withFooter: hasFooter,
316
476
  children: children
@@ -318,7 +478,7 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
318
478
  }) : null, /*#__PURE__*/_jsx(ConditionalWrapper, {
319
479
  WrapperComponent: DynamicWidthContainer,
320
480
  wrapperProps: imageWrapperStyleProps,
321
- condition: isImageWidthAdjustable,
481
+ condition: isImageWidthAdjustable || isHorizontalFullBleed || isVerticalFullBleed,
322
482
  children: /*#__PURE__*/_jsx(FullBleedContent, {
323
483
  borderRadius: fullBleedBorderRadius,
324
484
  ...fullBleedContentPropsClean,
@@ -334,7 +494,7 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
334
494
  })]
335
495
  });
336
496
  });
337
- const positionValues = ['none', 'bottom', 'left', 'right', 'top'];
497
+ const positionValues = Object.values(POSITION);
338
498
  const alignValues = ['start', 'end', 'center', 'stretch'];
339
499
  const PositionedFullBleedContentPropType = PropTypes.shape({
340
500
  position: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(positionValues)).isRequired,
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { selectSystemProps, StackView, Typography, useHash, useInputValue, useResponsiveProp, withLinkRouter, variantProp } from '@telus-uds/components-base';
3
+ import { selectSystemProps, StackView, Typography, useHash, useInputValue, useResponsiveProp, withLinkRouter, variantProp, resolveContentMaxWidth, useTheme } from '@telus-uds/components-base';
4
4
  import styled from 'styled-components';
5
5
  import { htmlAttrs, scrollToAnchor } from '../utils';
6
6
  import NavigationItem from './NavigationItem';
@@ -21,12 +21,28 @@ const Heading = /*#__PURE__*/styled.div.withConfig({
21
21
  letterSpacing: 0
22
22
  }
23
23
  });
24
+ const ContentWrapper = /*#__PURE__*/styled.div.withConfig({
25
+ displayName: "NavigationBar__ContentWrapper",
26
+ componentId: "components-web__sc-1vis1gt-1"
27
+ })(_ref => {
28
+ let {
29
+ maxWidth
30
+ } = _ref;
31
+ return {
32
+ width: '100%',
33
+ ...(maxWidth && {
34
+ maxWidth,
35
+ marginLeft: 'auto',
36
+ marginRight: 'auto'
37
+ })
38
+ };
39
+ });
24
40
 
25
41
  /**
26
42
  * NavigationBar can be used to allow customers to consistently navigate across
27
43
  * key pages within a specific product line
28
44
  */
29
- const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
45
+ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
30
46
  let {
31
47
  accessibilityRole = 'navigation',
32
48
  heading,
@@ -39,8 +55,9 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
39
55
  linkRouterProps,
40
56
  tokens,
41
57
  variant,
58
+ contentMaxWidth,
42
59
  ...rest
43
- } = _ref;
60
+ } = _ref2;
44
61
  const {
45
62
  currentValue,
46
63
  setValue
@@ -49,29 +66,35 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
49
66
  initialValue: selectedId,
50
67
  onChange
51
68
  });
69
+ const {
70
+ themeOptions
71
+ } = useTheme();
72
+ const contentWidthValue = useResponsiveProp(contentMaxWidth);
73
+ const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth);
74
+ const maxWidth = resolveContentMaxWidth(contentWidthValue, responsiveWidth);
52
75
  useHash((hash, event) => {
53
- let hashItem = hash && items.find(_ref2 => {
76
+ let hashItem = hash && items.find(_ref3 => {
54
77
  let {
55
78
  href
56
- } = _ref2;
79
+ } = _ref3;
57
80
  return hash === href;
58
81
  });
59
82
  if (!hashItem) {
60
- const parentItem = items.find(_ref3 => {
83
+ const parentItem = items.find(_ref4 => {
61
84
  let {
62
85
  items: parentItems
63
- } = _ref3;
64
- return parentItems?.some(_ref4 => {
86
+ } = _ref4;
87
+ return parentItems?.some(_ref5 => {
65
88
  let {
66
89
  href
67
- } = _ref4;
90
+ } = _ref5;
68
91
  return hash === href;
69
92
  });
70
93
  });
71
- hashItem = parentItem?.items.find(_ref5 => {
94
+ hashItem = parentItem?.items.find(_ref6 => {
72
95
  let {
73
96
  href
74
- } = _ref5;
97
+ } = _ref6;
75
98
  return hash === href;
76
99
  });
77
100
  }
@@ -138,7 +161,7 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
138
161
  }
139
162
  };
140
163
  }, [openSubMenuId, handleMouseDown]);
141
- return /*#__PURE__*/_jsxs(StackView, {
164
+ const stackView = /*#__PURE__*/_jsxs(StackView, {
142
165
  accessibilityRole: accessibilityRole,
143
166
  direction: direction,
144
167
  ref: navRef,
@@ -156,7 +179,7 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
156
179
  heading: headingLevel,
157
180
  children: heading
158
181
  })
159
- }), itemsForViewport?.map((_ref6, index) => {
182
+ }), itemsForViewport?.map((_ref7, index) => {
160
183
  let {
161
184
  href,
162
185
  label,
@@ -167,7 +190,7 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
167
190
  linkRouterProps: itemLinkRouterProps,
168
191
  items: nestedItems,
169
192
  ...itemRest
170
- } = _ref6;
193
+ } = _ref7;
171
194
  const itemId = id ?? label;
172
195
  const handleClick = event => {
173
196
  if (nestedItems) {
@@ -193,9 +216,7 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
193
216
  return /*#__PURE__*/_jsx(ItemComponent, {
194
217
  ref: itemRef,
195
218
  href: href,
196
- onClick: handleClick
197
- // TODO: refactor to pass selected ID via context
198
- ,
219
+ onClick: handleClick,
199
220
  selectedId: currentValue,
200
221
  index: index,
201
222
  LinkRouter: ItemLinkRouter,
@@ -219,6 +240,10 @@ const NavigationBar = /*#__PURE__*/React.forwardRef((_ref, ref) => {
219
240
  }, itemId);
220
241
  })]
221
242
  });
243
+ return maxWidth ? /*#__PURE__*/_jsx(ContentWrapper, {
244
+ maxWidth: maxWidth,
245
+ children: stackView
246
+ }) : stackView;
222
247
  });
223
248
  NavigationBar.displayName = 'NavigationBar';
224
249
  NavigationBar.propTypes = {
@@ -278,6 +303,23 @@ NavigationBar.propTypes = {
278
303
  /**
279
304
  * Variant configuration
280
305
  */
281
- variant: variantProp.propType
306
+ variant: variantProp.propType,
307
+ /**
308
+ * The maximum width of the content in the NavigationBar.
309
+ * This prop accepts responsive values for different viewports. If a number is provided,
310
+ * it will be the max content width for the desired viewport.
311
+ * - `xs`: 'max' | 'full' | <number>
312
+ * - `sm`: 'max' | 'full' | <number>
313
+ * - `md`: 'max' | 'full' | <number>
314
+ * - `lg`: 'max' | 'full' | <number>
315
+ * - `xl`: 'max' | 'full' | <number>
316
+ */
317
+ contentMaxWidth: PropTypes.shape({
318
+ xl: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
319
+ lg: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
320
+ md: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
321
+ sm: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
322
+ xs: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number])
323
+ })
282
324
  };
283
325
  export default NavigationBar;
@@ -12,7 +12,7 @@ const collapseItems = (items, selectedId) => {
12
12
  label,
13
13
  id
14
14
  } = _ref;
15
- return selectedId === id ?? label;
15
+ return selectedId === (id ?? label);
16
16
  };
17
17
 
18
18
  // Linter doesn't like for loops, simulate loop that breaks