@telus-uds/components-base 3.27.0 → 3.28.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +30 -5
  2. package/lib/cjs/Card/CardBase.js +12 -3
  3. package/lib/cjs/Carousel/Carousel.js +16 -15
  4. package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +3 -3
  5. package/lib/cjs/ExpandCollapse/Control.js +5 -1
  6. package/lib/cjs/ExpandCollapse/ExpandCollapse.js +17 -8
  7. package/lib/cjs/ExpandCollapse/Panel.js +7 -2
  8. package/lib/cjs/IconButton/IconButton.js +10 -5
  9. package/lib/cjs/Modal/Modal.js +21 -11
  10. package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +5 -1
  11. package/lib/cjs/Progress/Progress.js +19 -5
  12. package/lib/cjs/Progress/ProgressBar.js +22 -4
  13. package/lib/cjs/Progress/ProgressContext.js +11 -0
  14. package/lib/cjs/SideNav/Item.js +3 -3
  15. package/lib/cjs/SideNav/ItemsGroup.js +46 -19
  16. package/lib/cjs/SideNav/SideNav.js +29 -13
  17. package/lib/esm/Card/CardBase.js +12 -3
  18. package/lib/esm/Carousel/Carousel.js +16 -15
  19. package/lib/esm/Carousel/CarouselItem/CarouselItem.js +3 -3
  20. package/lib/esm/ExpandCollapse/Control.js +5 -1
  21. package/lib/esm/ExpandCollapse/ExpandCollapse.js +17 -8
  22. package/lib/esm/ExpandCollapse/Panel.js +7 -2
  23. package/lib/esm/IconButton/IconButton.js +10 -5
  24. package/lib/esm/Modal/Modal.js +21 -11
  25. package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +5 -1
  26. package/lib/esm/Progress/Progress.js +19 -5
  27. package/lib/esm/Progress/ProgressBar.js +22 -4
  28. package/lib/esm/Progress/ProgressContext.js +5 -0
  29. package/lib/esm/SideNav/Item.js +3 -3
  30. package/lib/esm/SideNav/ItemsGroup.js +45 -20
  31. package/lib/esm/SideNav/SideNav.js +29 -13
  32. package/lib/package.json +2 -2
  33. package/package.json +2 -2
  34. package/src/Card/CardBase.jsx +9 -3
  35. package/src/Carousel/Carousel.jsx +16 -15
  36. package/src/Carousel/CarouselItem/CarouselItem.jsx +3 -3
  37. package/src/ExpandCollapse/Control.jsx +1 -1
  38. package/src/ExpandCollapse/ExpandCollapse.jsx +9 -8
  39. package/src/ExpandCollapse/Panel.jsx +10 -2
  40. package/src/IconButton/IconButton.jsx +40 -28
  41. package/src/Modal/Modal.jsx +23 -11
  42. package/src/MultiSelectFilter/MultiSelectFilter.jsx +6 -1
  43. package/src/Progress/Progress.jsx +18 -7
  44. package/src/Progress/ProgressBar.jsx +19 -14
  45. package/src/Progress/ProgressContext.js +5 -0
  46. package/src/SideNav/Item.jsx +3 -3
  47. package/src/SideNav/ItemsGroup.jsx +36 -16
  48. package/src/SideNav/SideNav.jsx +22 -8
@@ -15,13 +15,28 @@ var _jsxRuntime = require("react/jsx-runtime");
15
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
16
  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); }
17
17
  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; }
18
- function selectBorderStyles(tokens) {
18
+ const selectContainerTokens = _ref => {
19
+ let {
20
+ borderWidth,
21
+ borderStyle,
22
+ borderColor
23
+ } = _ref;
19
24
  return {
20
- borderBottomWidth: tokens.borderWidth,
21
- borderBottomStyle: tokens.borderStyle,
22
- borderBottomColor: tokens.borderColor
25
+ borderTopWidth: borderWidth,
26
+ borderStyle,
27
+ borderColor
23
28
  };
24
- }
29
+ };
30
+ const selectItemTokens = function () {
31
+ let tokens = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
32
+ let isLastItem = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
33
+ return {
34
+ ...tokens,
35
+ ...(isLastItem ? {
36
+ borderWidth: 0
37
+ } : {})
38
+ };
39
+ };
25
40
  const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
26
41
 
27
42
  /**
@@ -29,7 +44,7 @@ const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_u
29
44
  - Use in conjunction with a large amount of educational / informational content
30
45
  - Allow the user to navigate between options frequently and efficiently
31
46
  */
32
- const SideNav = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
47
+ const SideNav = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
33
48
  let {
34
49
  children,
35
50
  variant = {},
@@ -38,7 +53,7 @@ const SideNav = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
38
53
  itemTokens,
39
54
  groupTokens,
40
55
  ...rest
41
- } = _ref;
56
+ } = _ref2;
42
57
  const themeTokens = (0, _ThemeProvider.useThemeTokens)('SideNav', tokens, variant);
43
58
  const [active, setActive] = _react.default.useState({
44
59
  groupId: undefined,
@@ -56,14 +71,15 @@ const SideNav = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
56
71
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ExpandCollapse.default, {
57
72
  ref: ref,
58
73
  maxOpen: accordion ? 1 : null,
59
- style: selectBorderStyles(themeTokens),
74
+ tokens: selectContainerTokens(themeTokens),
60
75
  ...selectProps(rest),
61
- children: _ref2 => {
76
+ children: _ref3 => {
62
77
  let {
63
78
  openIds,
64
79
  onToggle
65
- } = _ref2;
66
- const renderItem = (item, index, groupId) => {
80
+ } = _ref3;
81
+ const renderItem = function (item, index, groupId) {
82
+ let isLastItem = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
67
83
  const {
68
84
  itemId = `item-${index}`,
69
85
  onPress
@@ -81,7 +97,7 @@ const SideNav = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
81
97
  ...variant,
82
98
  type: 'child'
83
99
  } : variant,
84
- tokens: itemTokens,
100
+ tokens: selectItemTokens(itemTokens, isLastItem),
85
101
  isActive: isItemActive(itemId, groupId),
86
102
  onPress: handlePress
87
103
  });
@@ -105,7 +121,7 @@ const SideNav = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
105
121
  openGroups: openIds,
106
122
  isActive: isGroupActive,
107
123
  onToggle: handleToggle
108
- }, _react.default.Children.map(child.props.children, (item, itemIndex) => renderItem(item, itemIndex, groupId)));
124
+ }, _react.default.Children.map(child.props.children, (item, itemIndex) => renderItem(item, itemIndex, groupId, itemIndex === child.props.children.length - 1)));
109
125
  }
110
126
  return null;
111
127
  });
@@ -228,7 +228,13 @@ const CardBase = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
228
228
  cardState,
229
229
  ...rest
230
230
  } = _ref5;
231
- const cardStyle = selectStyles(typeof tokens === 'function' ? tokens(cardState) : tokens);
231
+ const resolvedTokens = typeof tokens === 'function' ? tokens(cardState) : tokens;
232
+ const tokensToUse = backgroundImage && backgroundImage.src ? {
233
+ ...resolvedTokens,
234
+ gradient: undefined,
235
+ backgroundGradient: undefined
236
+ } : resolvedTokens;
237
+ const cardStyle = selectStyles(tokensToUse);
232
238
  const props = selectProps(rest);
233
239
  let content = children;
234
240
  const {
@@ -301,7 +307,10 @@ const CardBase = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
301
307
  }
302
308
  });
303
309
  return /*#__PURE__*/_jsx(View, {
304
- style: containerStyle,
310
+ style: {
311
+ ...containerStyle,
312
+ borderRadius
313
+ },
305
314
  dataSet: dataSet,
306
315
  ref: ref,
307
316
  ...props,
@@ -379,7 +388,7 @@ const staticStyles = StyleSheet.create({
379
388
  contentOverlay: {
380
389
  position: 'relative',
381
390
  width: '100%',
382
- height: '100%',
391
+ minHeight: '100%',
383
392
  zIndex: 2
384
393
  },
385
394
  containContainer: {
@@ -84,7 +84,7 @@ const selectControlButtonPositionStyles = _ref => {
84
84
  isAutoPlayEnabled,
85
85
  viewport,
86
86
  maxWidth,
87
- viewportWidth
87
+ containerWidth
88
88
  } = _ref;
89
89
  const styles = {};
90
90
  let positionOffset = 0;
@@ -100,18 +100,19 @@ const selectControlButtonPositionStyles = _ref => {
100
100
  }
101
101
  }
102
102
  if (enablePeeking) {
103
- if (positionProperty === POSITION_PROPERTIES.RIGHT) {
104
- const rightMargin = (viewportWidth - maxWidth) / 2;
105
- positionOffset += rightMargin;
106
- } else if (positionProperty === POSITION_PROPERTIES.LEFT) {
107
- const leftMargin = (viewportWidth - maxWidth) / 2;
108
- positionOffset += leftMargin;
109
- }
103
+ const {
104
+ peekingMiddleSpace,
105
+ peekingGap
106
+ } = getPeekingProps(viewport);
107
+ const clampedMaxWidth = Math.min(maxWidth || containerWidth, containerWidth);
108
+ const slideRightEdge = (containerWidth + clampedMaxWidth) / 2 - peekingMiddleSpace;
109
+ const buttonCenter = slideRightEdge + peekingGap / 2;
110
+ positionOffset = containerWidth - buttonCenter - buttonWidth / 2;
110
111
  }
111
112
  styles[positionProperty] = positionOffset;
112
113
  return styles;
113
114
  };
114
- const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, viewportWidth) => {
115
+ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, containerWidth) => {
115
116
  const styles = {
116
117
  zIndex: 1,
117
118
  position: 'absolute'
@@ -135,7 +136,7 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
135
136
  isAutoPlayEnabled,
136
137
  viewport,
137
138
  maxWidth,
138
- viewportWidth
139
+ containerWidth
139
140
  })
140
141
  };
141
142
  };
@@ -272,7 +273,7 @@ const calculateFinalWidth = (containerWidth, enablePeeking, viewport, maxWidth)
272
273
  peekingGap,
273
274
  peekingMiddleSpace
274
275
  } = getPeekingProps(viewport);
275
- const baseWidth = maxWidth || containerWidth;
276
+ const baseWidth = Math.min(maxWidth || containerWidth, containerWidth);
276
277
  finalWidth = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER + peekingGap;
277
278
  }
278
279
  return finalWidth;
@@ -492,7 +493,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
492
493
  peekingMiddleSpace
493
494
  } = getPeekingProps(viewport);
494
495
  let finalWidth;
495
- const baseWidth = maxWidth || containerLayoutRef.current.width;
496
+ const baseWidth = Math.min(maxWidth || containerLayoutRef.current.width, containerLayoutRef.current.width);
496
497
  const slideWide = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER;
497
498
  if (activeIndexRef.current === 0) {
498
499
  finalWidth = 0;
@@ -1014,7 +1015,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
1014
1015
  isAutoPlayEnabled,
1015
1016
  viewport,
1016
1017
  maxWidth,
1017
- viewportWidth: currentViewportWidth
1018
+ containerWidth: containerLayout.width
1018
1019
  })],
1019
1020
  children: /*#__PURE__*/_jsx(IconButton, {
1020
1021
  icon: isCarouselPlaying ? pauseIcon : playIcon,
@@ -1023,7 +1024,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
1023
1024
  onPress: onAnimationControlButtonPress
1024
1025
  })
1025
1026
  }) : null, showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/_jsx(View, {
1026
- style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
1027
+ style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, containerLayout.width),
1027
1028
  testID: "previous-button-container",
1028
1029
  children: /*#__PURE__*/_jsx(IconButton, {
1029
1030
  onLayout: onPreviousNextNavigationButtonLayout,
@@ -1083,7 +1084,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
1083
1084
  })
1084
1085
  })
1085
1086
  }), showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/_jsx(View, {
1086
- style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
1087
+ style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, containerLayout.width),
1087
1088
  testID: "next-button-container",
1088
1089
  children: /*#__PURE__*/_jsx(IconButton, {
1089
1090
  onLayout: onPreviousNextNavigationButtonLayout,
@@ -24,10 +24,10 @@ const selectContainerStyle = _ref => {
24
24
  let marginLeft = 0;
25
25
  if (enablePeeking) {
26
26
  const isFirst = elementIndex === 0;
27
- const baseWidth = maxWidth || width;
28
- adjustedWidth = baseWidth - peekingMiddleSpace * 2;
27
+ const clampedMaxWidth = Math.min(maxWidth || width, width);
28
+ adjustedWidth = clampedMaxWidth - peekingMiddleSpace * 2;
29
29
  if (isFirst) {
30
- marginLeft = peekingMiddleSpace + (viewportWidth - maxWidth) / 2;
30
+ marginLeft = peekingMiddleSpace + (viewportWidth - clampedMaxWidth) / 2;
31
31
  } else {
32
32
  marginLeft = peekingGap;
33
33
  }
@@ -57,7 +57,11 @@ function selectIconContainerStyles(_ref2) {
57
57
  const paddingSide = iconPosition === 'right' ? 'paddingLeft' : 'paddingRight';
58
58
  return {
59
59
  [paddingSide]: iconGap,
60
- paddingTop: iconPaddingTop
60
+ ...(iconPaddingTop && {
61
+ transform: [{
62
+ translateY: iconPaddingTop
63
+ }]
64
+ })
61
65
  };
62
66
  }
63
67
  function selectTextContainerStyles(_ref3) {
@@ -6,13 +6,22 @@ import { useThemeTokens } from '../ThemeProvider';
6
6
  import { a11yProps, getTokensPropType, selectSystemProps, useMultipleInputValues, variantProp, viewProps, contentfulProps, useUniqueId } from '../utils';
7
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
8
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps, contentfulProps]);
9
- function selectBorderStyles(tokens) {
9
+ const selectWrapperStyles = _ref => {
10
+ let {
11
+ borderWidth,
12
+ borderTopWidth,
13
+ borderStyle,
14
+ borderColor
15
+ } = _ref;
10
16
  return {
11
- borderBottomWidth: tokens.borderWidth,
12
- borderBottomStyle: tokens.borderStyle,
13
- borderBottomColor: tokens.borderColor
17
+ borderStyle,
18
+ borderColor,
19
+ borderTopWidth,
20
+ borderBottomWidth: borderWidth,
21
+ borderBottomStyle: borderStyle,
22
+ borderBottomColor: borderColor
14
23
  };
15
- }
24
+ };
16
25
 
17
26
  /**
18
27
  * Flexible base component for lists where some or all items are collapsible headers.
@@ -21,7 +30,7 @@ function selectBorderStyles(tokens) {
21
30
  * <ExpandCollapse.Panel> children, and assign the panels explicit `panelId` props. The panels may be
22
31
  * nested (they do not need to be direct children), and non-interactive items may be included too.
23
32
  */
24
- const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
33
+ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
25
34
  let {
26
35
  children,
27
36
  tokens,
@@ -32,7 +41,7 @@ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
32
41
  onChange,
33
42
  dataSet,
34
43
  ...rest
35
- } = _ref;
44
+ } = _ref2;
36
45
  const instanceId = useUniqueId('ExpandCollapse');
37
46
  const {
38
47
  currentValues: openIds,
@@ -53,7 +62,7 @@ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
53
62
  ...selectProps(rest),
54
63
  dataSet: dataSet,
55
64
  children: /*#__PURE__*/_jsx(View, {
56
- style: selectBorderStyles(themeTokens),
65
+ style: selectWrapperStyles(themeTokens),
57
66
  children: typeof children === 'function' ? children({
58
67
  openIds,
59
68
  onToggle,
@@ -103,6 +103,7 @@ const ExpandCollapsePanel = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
103
103
  controlRef,
104
104
  content,
105
105
  copy = 'en',
106
+ disableMobileScrollBuffer = false,
106
107
  ...rest
107
108
  } = _ref5;
108
109
  const [containerHeight, setContainerHeight] = React.useState(null);
@@ -124,7 +125,7 @@ const ExpandCollapsePanel = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
124
125
 
125
126
  // on mobile devices we require a scroll buffer equal to the font size
126
127
  // to avoid triggering scrolling unnecessarily
127
- const mobileScrollBuffer = Platform.OS === 'web' ? 0 : selectTextStyles(themeTokens)?.fontSize;
128
+ const mobileScrollBuffer = Platform.OS === 'web' || disableMobileScrollBuffer ? 0 : selectTextStyles(themeTokens)?.fontSize;
128
129
  const handleControlPress = event => {
129
130
  onToggle?.(panelId, event);
130
131
  if (onPress) onPress(panelId, event);
@@ -271,6 +272,10 @@ ExpandCollapsePanel.propTypes = {
271
272
  /**
272
273
  * A boolean prop to determine if the panel is a content panel or not. If true, the panel will not have a control
273
274
  */
274
- content: PropTypes.bool
275
+ content: PropTypes.bool,
276
+ /**
277
+ * A boolean prop to disable the extra scroll buffer on mobile devices (only applicable on iOS/Android, ignored on web)
278
+ */
279
+ disableMobileScrollBuffer: PropTypes.bool
275
280
  };
276
281
  export default ExpandCollapsePanel;
@@ -79,6 +79,11 @@ const selectInnerStyle = (_ref2, password) => {
79
79
  width,
80
80
  height
81
81
  } = _ref2;
82
+ const basePadding = calculatePadding(padding, borderWidth);
83
+ const calculateSpecificPadding = (specificPadding, specificBorderWidth) => {
84
+ const calculated = calculatePadding(specificPadding ?? padding, specificBorderWidth ?? borderWidth);
85
+ return calculated !== basePadding && calculated !== undefined ? calculated : undefined;
86
+ };
82
87
  return {
83
88
  // Inner borders animate with the icon and should be treated like a themable feature of the icon
84
89
  borderColor,
@@ -92,11 +97,11 @@ const selectInnerStyle = (_ref2, password) => {
92
97
  borderRightWidth,
93
98
  borderBottomWidth,
94
99
  borderLeftWidth,
95
- padding: calculatePadding(padding, borderWidth),
96
- paddingLeft: calculatePadding(paddingLeft, borderLeftWidth),
97
- paddingRight: calculatePadding(paddingRight, borderRightWidth),
98
- paddingTop: calculatePadding(paddingTop, borderTopWidth),
99
- paddingBottom: calculatePadding(paddingBottom, borderBottomWidth),
100
+ padding: basePadding,
101
+ paddingLeft: calculateSpecificPadding(paddingLeft, borderLeftWidth),
102
+ paddingRight: calculateSpecificPadding(paddingRight, borderRightWidth),
103
+ paddingTop: calculateSpecificPadding(paddingTop, borderTopWidth),
104
+ paddingBottom: calculateSpecificPadding(paddingBottom, borderBottomWidth),
100
105
  ...Platform.select({
101
106
  web: {
102
107
  pointerEvents: 'none',
@@ -64,11 +64,15 @@ const selectModalStyles = _ref2 => {
64
64
  const selectBackdropStyles = _ref3 => {
65
65
  let {
66
66
  backdropColor,
67
- backdropOpacity
67
+ backdropOpacity,
68
+ backdropCursor
68
69
  } = _ref3;
69
70
  return {
70
71
  backgroundColor: backdropColor,
71
- opacity: backdropOpacity
72
+ opacity: backdropOpacity,
73
+ ...(Platform.OS === 'web' && backdropCursor ? {
74
+ cursor: backdropCursor
75
+ } : {})
72
76
  };
73
77
  };
74
78
  const selectCloseButtonContainerStyles = _ref4 => {
@@ -121,12 +125,15 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
121
125
  cancelButtonText,
122
126
  cancelButtonType,
123
127
  footer,
128
+ backgroundDismissible = true,
124
129
  ...rest
125
130
  } = _ref5;
126
131
  const viewport = useViewport();
132
+ const isBackdropClickable = onClose && backgroundDismissible;
127
133
  const themeTokens = useThemeTokens('Modal', tokens, variant, {
128
134
  viewport,
129
- maxWidth
135
+ maxWidth,
136
+ backdropCursor: isBackdropClickable ? 'pointer' : 'default'
130
137
  });
131
138
  const modalRef = useScrollBlocking(isOpen);
132
139
  const modalBodyRef = React.useRef(ref);
@@ -232,7 +239,7 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
232
239
  })]
233
240
  })
234
241
  }), /*#__PURE__*/_jsx(TouchableWithoutFeedback, {
235
- onPress: handleClose,
242
+ onPress: isBackdropClickable && handleClose,
236
243
  children: /*#__PURE__*/_jsx(View, {
237
244
  style: [staticStyles.backdrop, selectBackdropStyles(themeTokens)]
238
245
  })
@@ -329,7 +336,15 @@ Modal.propTypes = {
329
336
  /**
330
337
  * Receive a react node or an array of nodes to render at the bottom of the modal, above the action buttons.
331
338
  */
332
- footer: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
339
+ footer: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
340
+ /**
341
+ * Controls whether the modal can be dismissed by clicking on the backdrop.
342
+ * When set to `false`, clicking the backdrop will not close the modal.
343
+ * The backdrop cursor automatically changes to 'default' to indicate it's not clickable.
344
+ * Note: Backdrop dismissal requires `onClose` to be defined.
345
+ * @default true
346
+ */
347
+ backgroundDismissible: PropTypes.bool
333
348
  };
334
349
  export default Modal;
335
350
  const staticStyles = StyleSheet.create({
@@ -339,12 +354,7 @@ const staticStyles = StyleSheet.create({
339
354
  left: 0,
340
355
  right: 0,
341
356
  bottom: 0,
342
- zIndex: -1,
343
- ...Platform.select({
344
- web: {
345
- cursor: 'pointer'
346
- }
347
- })
357
+ zIndex: -1
348
358
  },
349
359
  positioningContainer: {
350
360
  flexBasis: '100%',
@@ -178,6 +178,11 @@ const MultiSelectFilter = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
178
178
  setMaxWidth(items.length >= rowLimit);
179
179
  }, [items.length, rowLimit]);
180
180
  React.useEffect(() => setCheckedIds(currentValues ?? []), [currentValues]);
181
+ React.useEffect(() => {
182
+ if (isOpen && onOpen) {
183
+ onOpen();
184
+ }
185
+ }, [isOpen, onOpen]);
181
186
  const uniqueFields = ['id', 'label'];
182
187
  if (!containUniqueFields(items, uniqueFields)) {
183
188
  throw new Error(`MultiSelectFilter items must have unique ${uniqueFields.join(', ')}`);
@@ -190,7 +195,6 @@ const MultiSelectFilter = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
190
195
  }]);
191
196
  const handleChange = event => {
192
197
  if (pressHandlers.onPress) pressHandlers?.onPress(event);
193
- if (isOpen) onOpen();
194
198
  setIsOpen(!isOpen);
195
199
  };
196
200
  const onApply = e => {
@@ -4,6 +4,7 @@ import View from "react-native-web/dist/exports/View";
4
4
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
5
  import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
6
6
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
7
+ import ProgressContext from './ProgressContext';
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
8
9
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
9
10
  const selectProgressStyles = _ref => {
@@ -47,6 +48,12 @@ const selectProgressStyles = _ref => {
47
48
  *
48
49
  * - Use the `size` variant to control the height of your progress bars: passing `'mini'` will make your
49
50
  * progress bar container narrower.
51
+ * - Use the `layers` variant to control how multiple progress bars are positioned:
52
+ * - `false` (default): bars are positioned vertically one below the other.
53
+ * - `true`: bars overlay on top of each other (layered/stacked on z-axis).
54
+ * Note: The `layers` prop is deprecated. After August 2026, `layers: true` will become the permanent
55
+ * default behavior and the `layers` prop will be removed. To maintain vertical layout after removal,
56
+ * use separate individual Progress components.
50
57
  *
51
58
  * ## Usability and A11y guidelines
52
59
  *
@@ -63,11 +70,18 @@ const Progress = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
63
70
  ...rest
64
71
  } = _ref2;
65
72
  const themeTokens = useThemeTokens('Progress', tokens, variant);
66
- return /*#__PURE__*/_jsx(View, {
67
- ref: ref,
68
- style: [staticStyles.progressContainer, selectProgressStyles(themeTokens)],
69
- ...selectProps(rest),
70
- children: children
73
+ // Default to false (vertical layout) to preserve existing behavior and avoid breaking changes
74
+ const layers = variant?.layers ?? false;
75
+ return /*#__PURE__*/_jsx(ProgressContext.Provider, {
76
+ value: {
77
+ layers
78
+ },
79
+ children: /*#__PURE__*/_jsx(View, {
80
+ ref: ref,
81
+ style: [staticStyles.progressContainer, selectProgressStyles(themeTokens)],
82
+ ...selectProps(rest),
83
+ children: children
84
+ })
71
85
  });
72
86
  });
73
87
  Progress.displayName = 'Progress';
@@ -7,16 +7,23 @@ import ProgressBarBackground from './ProgressBarBackground';
7
7
  import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
8
8
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
9
9
  import { MAX_PERCENT_VALUE, MIN_PERCENT_VALUE } from './constants';
10
+ import ProgressContext from './ProgressContext';
10
11
  import { jsx as _jsx } from "react/jsx-runtime";
11
12
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
12
- const selectBarStyles = (_ref, calculatedPercentage, barPosition) => {
13
+ const selectBarStyles = _ref => {
13
14
  let {
15
+ themeTokens,
16
+ calculatedPercentage,
17
+ barPosition,
18
+ layers
19
+ } = _ref;
20
+ const {
14
21
  backgroundColor,
15
22
  borderRadius,
16
23
  outlineWidth,
17
24
  outlineColor,
18
25
  shadow
19
- } = _ref;
26
+ } = themeTokens;
20
27
  return {
21
28
  backgroundColor,
22
29
  borderRadius,
@@ -24,7 +31,10 @@ const selectBarStyles = (_ref, calculatedPercentage, barPosition) => {
24
31
  outlineColor,
25
32
  ...applyShadowToken(shadow),
26
33
  width: `${calculatedPercentage}%`,
27
- left: `${barPosition}%`
34
+ left: `${barPosition}%`,
35
+ ...(layers ? {
36
+ position: 'absolute'
37
+ } : {})
28
38
  };
29
39
  };
30
40
 
@@ -75,6 +85,9 @@ const ProgressBar = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
75
85
  },
76
86
  ...rest
77
87
  } = _ref2;
88
+ const {
89
+ layers
90
+ } = React.useContext(ProgressContext);
78
91
  const {
79
92
  items,
80
93
  current
@@ -107,7 +120,12 @@ const ProgressBar = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
107
120
  });
108
121
  return percentage > MIN_PERCENT_VALUE || items ? /*#__PURE__*/_jsx(View, {
109
122
  ref: ref,
110
- style: [staticStyles.bar, selectBarStyles(themeTokens, calculatedPercentage, barPosition)],
123
+ style: [staticStyles.bar, selectBarStyles({
124
+ themeTokens,
125
+ calculatedPercentage,
126
+ barPosition,
127
+ layers
128
+ })],
111
129
  ...selectedProps,
112
130
  children: children ?? /*#__PURE__*/_jsx(ProgressBarBackground, {
113
131
  variant: variant
@@ -0,0 +1,5 @@
1
+ import { createContext } from 'react';
2
+ const ProgressContext = /*#__PURE__*/createContext({
3
+ layers: false
4
+ });
5
+ export default ProgressContext;
@@ -22,9 +22,9 @@ function selectItemStyles(_ref) {
22
22
  } = _ref;
23
23
  return {
24
24
  backgroundColor,
25
- borderTopColor: borderColor,
26
- borderTopWidth: borderWidth,
27
- borderTopStyle: borderStyle,
25
+ borderBottomColor: borderColor,
26
+ borderBottomWidth: borderWidth,
27
+ borderBottomStyle: borderStyle,
28
28
  paddingLeft,
29
29
  paddingRight,
30
30
  paddingTop,