@telus-uds/components-base 3.22.0 → 3.23.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/lib/cjs/Button/Button.js +2 -0
  3. package/lib/cjs/Button/ButtonBase.js +10 -5
  4. package/lib/cjs/Button/ButtonDropdown.js +2 -0
  5. package/lib/cjs/Button/ButtonGroup.js +45 -38
  6. package/lib/cjs/Button/propTypes.js +6 -0
  7. package/lib/cjs/Carousel/Carousel.js +52 -19
  8. package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +23 -3
  9. package/lib/cjs/Icon/Icon.js +8 -11
  10. package/lib/cjs/Icon/IconText.js +0 -1
  11. package/lib/cjs/Listbox/GroupControl.js +33 -39
  12. package/lib/cjs/Listbox/Listbox.js +22 -13
  13. package/lib/cjs/Listbox/ListboxGroup.js +2 -1
  14. package/lib/cjs/Listbox/ListboxOverlay.js +5 -2
  15. package/lib/cjs/Listbox/PressableItem.js +8 -4
  16. package/lib/cjs/TextInput/TextInputBase.js +5 -1
  17. package/lib/cjs/Validator/Validator.js +171 -135
  18. package/lib/esm/Button/Button.js +2 -0
  19. package/lib/esm/Button/ButtonBase.js +10 -5
  20. package/lib/esm/Button/ButtonDropdown.js +2 -0
  21. package/lib/esm/Button/ButtonGroup.js +44 -39
  22. package/lib/esm/Button/propTypes.js +6 -0
  23. package/lib/esm/Carousel/Carousel.js +52 -19
  24. package/lib/esm/Carousel/CarouselItem/CarouselItem.js +23 -3
  25. package/lib/esm/Icon/Icon.js +8 -11
  26. package/lib/esm/Icon/IconText.js +0 -1
  27. package/lib/esm/Listbox/GroupControl.js +33 -39
  28. package/lib/esm/Listbox/Listbox.js +23 -14
  29. package/lib/esm/Listbox/ListboxGroup.js +2 -1
  30. package/lib/esm/Listbox/ListboxOverlay.js +5 -2
  31. package/lib/esm/Listbox/PressableItem.js +8 -4
  32. package/lib/esm/TextInput/TextInputBase.js +5 -1
  33. package/lib/esm/Validator/Validator.js +171 -135
  34. package/lib/package.json +2 -2
  35. package/package.json +2 -2
  36. package/src/Button/Button.jsx +2 -1
  37. package/src/Button/ButtonBase.jsx +18 -12
  38. package/src/Button/ButtonDropdown.jsx +2 -0
  39. package/src/Button/ButtonGroup.jsx +62 -45
  40. package/src/Button/propTypes.js +6 -0
  41. package/src/Carousel/Carousel.jsx +58 -5
  42. package/src/Carousel/CarouselItem/CarouselItem.jsx +31 -3
  43. package/src/Icon/Icon.jsx +11 -14
  44. package/src/Icon/IconText.jsx +0 -1
  45. package/src/Listbox/GroupControl.jsx +41 -47
  46. package/src/Listbox/Listbox.jsx +26 -9
  47. package/src/Listbox/ListboxGroup.jsx +2 -1
  48. package/src/Listbox/ListboxOverlay.jsx +7 -2
  49. package/src/Listbox/PressableItem.jsx +8 -4
  50. package/src/TextInput/TextInputBase.jsx +5 -1
  51. package/src/Validator/Validator.jsx +180 -159
package/CHANGELOG.md CHANGED
@@ -1,9 +1,26 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Wed, 29 Oct 2025 07:40:46 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 19 Nov 2025 05:51:39 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.23.0
8
+
9
+ Wed, 19 Nov 2025 05:51:39 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `Listbox`: Added test and snapshot for Listbox (david.melara1@telus.com)
14
+ - `Listbox`: Updated style for koodo, allium and public mobile; added new style variant (david.melara1@telus.com)
15
+ - `ButtonGroup`: enhacements for iOS and android implemented and fix for the mobile version (35577399+JoshHC@users.noreply.github.com)
16
+ - `Button`: Implement heightFull prop (oscar.palencia@telus.com)
17
+ - Bump @telus-uds/system-theme-tokens to v4.16.0
18
+
19
+ ### Patches
20
+
21
+ - `Validator`: code refactored to resolve several bugs (35577399+JoshHC@users.noreply.github.com)
22
+ - `Carousel`: fix tab navigation (guillermo.peitzner@telus.com)
23
+
7
24
  ## 3.22.0
8
25
 
9
26
  Wed, 29 Oct 2025 07:40:46 GMT
@@ -19,6 +19,7 @@ const Button = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
19
19
  accessibilityRole = 'button',
20
20
  tokens,
21
21
  variant,
22
+ heightFull = true,
22
23
  ...props
23
24
  } = _ref;
24
25
  const viewport = (0, _ViewportProvider.useViewport)();
@@ -36,6 +37,7 @@ const Button = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
36
37
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ButtonBase.default, {
37
38
  ...props,
38
39
  tokens: getTokens,
40
+ heightFull: heightFull,
39
41
  accessibilityRole: accessibilityRole,
40
42
  ref: ref,
41
43
  viewport: viewport
@@ -40,23 +40,27 @@ const selectFlexAndWidthStyles = _ref2 => {
40
40
  }
41
41
  return styles;
42
42
  };
43
- const selectOuterContainerStyles = _ref3 => {
43
+ const selectOuterContainerStyles = (_ref3, heightFull) => {
44
44
  let {
45
45
  opacity,
46
46
  outerBorderColor,
47
47
  outerBorderWidth,
48
48
  outerBorderGap,
49
49
  borderRadius,
50
- outerBackgroundColor
50
+ outerBackgroundColor,
51
+ alignSelf
51
52
  } = _ref3;
52
53
  return {
54
+ backgroundColor: outerBackgroundColor,
55
+ opacity,
53
56
  ..._Platform.default.select({
54
57
  native: {
58
+ alignSelf: alignSelf !== undefined ? alignSelf : 'flex-start'
59
+ },
60
+ web: heightFull ? {} : {
55
61
  alignSelf: 'flex-start'
56
62
  }
57
63
  }),
58
- backgroundColor: outerBackgroundColor,
59
- opacity,
60
64
  ...(0, _ThemeProvider.applyOuterBorder)({
61
65
  outerBorderGap,
62
66
  outerBorderWidth,
@@ -255,6 +259,7 @@ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref12, ref) => {
255
259
  icon,
256
260
  iconPosition = icon ? 'left' : undefined,
257
261
  iconProps,
262
+ heightFull = true,
258
263
  ...rawRest
259
264
  } = _ref12;
260
265
  const {
@@ -314,7 +319,7 @@ const ButtonBase = /*#__PURE__*/_react.default.forwardRef((_ref12, ref) => {
314
319
  }
315
320
  const themeTokens = resolveButtonTokens(pressableState);
316
321
  const flexAndWidthStyles = themeTokens.width === '100%' && themeTokens.flex === 1 ? selectFlexAndWidthStyles(themeTokens) : {};
317
- return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens), ...(Object.keys(flexAndWidthStyles).length > 0 ? [flexAndWidthStyles] : []), selectOuterSizeStyles(themeTokens)];
322
+ return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens, heightFull), ...(Object.keys(flexAndWidthStyles).length > 0 ? [flexAndWidthStyles] : []), selectOuterSizeStyles(themeTokens)];
318
323
  };
319
324
  const dataSetProp = flexAndWidthStylesIds || rawRest.dataSet ? {
320
325
  dataSet: {
@@ -112,6 +112,7 @@ const ButtonDropdown = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
112
112
  accessibilityRole = 'radio',
113
113
  description,
114
114
  singleOption,
115
+ heightFull = true,
115
116
  ...props
116
117
  } = _ref2;
117
118
  const isFullWidth = variant?.width === FULL_WIDTH_STYLE;
@@ -154,6 +155,7 @@ const ButtonDropdown = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
154
155
  ...pressHandlers,
155
156
  onPress: handlePress,
156
157
  tokens: getButtonTokens,
158
+ heightFull: heightFull,
157
159
  inactive: singleOption || inactive,
158
160
  icon: () => null,
159
161
  accessibilityRole: accessibilityRole,
@@ -4,12 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _airbnbPropTypes = _interopRequireDefault(require("airbnb-prop-types"));
10
10
  var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
11
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
12
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
11
13
  var _ButtonBase = _interopRequireDefault(require("./ButtonBase"));
12
- var _StackView = require("../StackView");
13
14
  var _Fieldset = _interopRequireDefault(require("../Fieldset"));
14
15
  var _ViewportProvider = require("../ViewportProvider");
15
16
  var _ThemeProvider = require("../ThemeProvider");
@@ -17,17 +18,10 @@ var _utils = require("../utils");
17
18
  var _pressability = require("../utils/pressability");
18
19
  var _jsxRuntime = require("react/jsx-runtime");
19
20
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
21
+ 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); }
22
+ 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; }
20
23
  const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
21
24
  const [selectItemProps, selectedItemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.focusHandlerProps, _utils.pressProps, _utils.viewProps]);
22
- const getStackWrapTokens = variant => {
23
- return _Platform.default.select({
24
- web: {
25
- justifyContent: variant?.width === 'equal' ? 'space-evenly' : 'flex-start',
26
- width: variant?.width === 'equal' ? '100%' : 'auto'
27
- },
28
- default: {}
29
- });
30
- };
31
25
  const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
32
26
  let {
33
27
  variant,
@@ -60,12 +54,6 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
60
54
  const themeTokens = (0, _ThemeProvider.useThemeTokens)('ButtonGroup', tokens, variant, {
61
55
  viewport
62
56
  });
63
- const themeStackTokens = (0, _utils.selectTokens)('StackView', themeTokens);
64
- const variantStackTokens = getStackWrapTokens(variant);
65
- const stackTokens = {
66
- ...themeStackTokens,
67
- ...variantStackTokens
68
- };
69
57
  const {
70
58
  direction,
71
59
  space,
@@ -75,15 +63,34 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
75
63
  padding,
76
64
  gap
77
65
  } = themeTokens;
66
+ const isMobileNonContained = _Platform.default.OS !== 'web' && (!variant || variant?.style !== 'contained');
78
67
  const themeButtonTokensCallback = (0, _ThemeProvider.useThemeTokensCallback)('ButtonGroupItem', tokens, variant);
79
- const getButtonTokens = state => {
68
+ const gapValue = (0, _utils.useSpacingScale)(gap || space);
69
+ const getButtonTokens = (0, _react.useCallback)(state => {
80
70
  const themeButtonTokens = themeButtonTokensCallback(state);
71
+ const shouldUseTransparentBackground = isMobileNonContained && !state.selected && !state.pressed && !state.hover && !state.focus;
81
72
  return {
82
73
  ...themeButtonTokens,
83
- width: variant?.width === 'equal' ? '100%' : 'auto',
84
- flex: variant?.width === 'equal' ? 1 : undefined
74
+ ...(variant?.width === 'equal' && staticStyles.equalWidth),
75
+ ...(shouldUseTransparentBackground && {
76
+ backgroundColor: 'transparent'
77
+ }),
78
+ alignSelf: themeButtonTokens.width ? 'flex-start' : 'center'
85
79
  };
86
- };
80
+ }, [themeButtonTokensCallback, isMobileNonContained, variant?.width]);
81
+ const fieldsetStyles = (0, _react.useMemo)(() => ({
82
+ ...staticStyles.fieldsetBase,
83
+ borderRadius,
84
+ backgroundColor: isMobileNonContained ? 'transparent' : backgroundColor || 'transparent',
85
+ padding,
86
+ width: variant?.width === 'equal' ? '100%' : 'auto'
87
+ }), [borderRadius, backgroundColor, padding, variant?.width, isMobileNonContained]);
88
+ const viewStyles = (0, _react.useMemo)(() => ({
89
+ ...staticStyles.viewBase,
90
+ flexDirection: direction === 'column' ? 'column' : 'row',
91
+ gap: gapValue || 0,
92
+ justifyContent: variant?.width === 'equal' ? 'space-evenly' : 'flex-start'
93
+ }), [direction, gapValue, variant?.width]);
87
94
  const {
88
95
  currentValues,
89
96
  toggleOneValue
@@ -120,25 +127,11 @@ const ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
120
127
  inactive: inactive,
121
128
  validation: validation,
122
129
  accessibilityRole: accessibilityRole,
123
- style: {
124
- borderRadius,
125
- backgroundColor,
126
- padding,
127
- ...(_Platform.default.OS === 'web' ? {
128
- gap,
129
- width: variant?.width === 'equal' ? '100%' : 'auto'
130
- } : {
131
- alignSelf: 'flex-start'
132
- })
133
- },
130
+ style: fieldsetStyles,
134
131
  ...selectProps(rest),
135
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_StackView.StackWrap, {
132
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
136
133
  accessibilityRole: innerRole,
137
- space: space,
138
- direction: direction,
139
- tokens: stackTokens,
140
- gap: gap,
141
- ref: ref,
134
+ style: viewStyles,
142
135
  children: items.map((_ref2, index) => {
143
136
  let {
144
137
  label,
@@ -298,4 +291,18 @@ ButtonGroup.propTypes = {
298
291
  */
299
292
  copy: _propTypes.default.oneOf(['en', 'fr'])
300
293
  };
294
+ const staticStyles = _StyleSheet.default.create({
295
+ fieldsetBase: {
296
+ alignSelf: 'flex-start',
297
+ display: 'inline'
298
+ },
299
+ viewBase: {
300
+ flexWrap: 'wrap',
301
+ alignItems: 'center'
302
+ },
303
+ equalWidth: {
304
+ width: '100%',
305
+ flex: 1
306
+ }
307
+ });
301
308
  var _default = exports.default = ButtonGroup;
@@ -13,6 +13,12 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
13
13
  const textAndA11yText = exports.textAndA11yText = _airbnbPropTypes.default.childrenOf(_propTypes.default.oneOfType([_airbnbPropTypes.default.elementType(_A11yText.default), _propTypes.default.string]));
14
14
  const buttonPropTypes = {
15
15
  tokens: (0, _props.getTokensPropType)('Button'),
16
+ /**
17
+ * If true, the button will honor the align-items value from its parent flex container.
18
+ * If false, the button will always align to 'flex-start' in a flex container.
19
+ * Currently, `heightFull`'s default behaviour will expand to the full height of its parent's flex container. In an upcoming major release, the default behaviour will be changed to expand based on the content. To maintain the expected behaviour, you must explicitly set `heightFull: true`
20
+ */
21
+ heightFull: _propTypes.default.bool,
16
22
  /**
17
23
  * If true, prevents the button from being pressed, changes the cursor (on web) and accessibility
18
24
  * attributes to communicate this to the user, and applies `inactive: true` appearances from the theme
@@ -364,6 +364,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
364
364
  ...rest
365
365
  } = _ref3;
366
366
  let childrenArray = (0, _utils.unpackFragment)(children);
367
+ const isTransitioningRef = _react.default.useRef(false);
367
368
  const viewport = (0, _ViewportProvider.useViewport)();
368
369
  const totalItems = getTotalItems(enableDisplayMultipleItemsPerSlide, childrenArray, viewport);
369
370
  const autoPlayFeatureEnabled = autoPlay && slideDuration > 0 && transitionDuration > 0 && totalItems > 1;
@@ -434,9 +435,14 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
434
435
  setIsAnimating(true);
435
436
  }, [onAnimationStart]);
436
437
  const handleAnimationEnd = _react.default.useCallback(function () {
437
- if (typeof onAnimationEnd === 'function') onAnimationEnd(...arguments);
438
- setIsAnimating(false);
439
- }, [onAnimationEnd]);
438
+ var _ref4;
439
+ const result = (_ref4 = arguments.length - 1, _ref4 < 0 || arguments.length <= _ref4 ? undefined : arguments[_ref4]);
440
+ if (result?.finished) {
441
+ if (typeof onAnimationEnd === 'function') onAnimationEnd(...arguments);
442
+ setIsAnimating(false);
443
+ isTransitioningRef.current = false;
444
+ }
445
+ }, [onAnimationEnd, isTransitioningRef]);
440
446
  const updateOffset = _react.default.useCallback(() => {
441
447
  if (enablePeeking) {
442
448
  const {
@@ -544,6 +550,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
544
550
  }
545
551
  const index = activeIndexRef.current + calcDelta;
546
552
  if (skipChanges) {
553
+ isTransitioningRef.current = true;
547
554
  animate(pan, toValue, index);
548
555
  if (enableHero) {
549
556
  animate(heroPan, toValue, index);
@@ -559,6 +566,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
559
566
  y: 0
560
567
  };
561
568
  heroToValue.x = heroContainerLayoutRef.current.width * -1 * calcDelta;
569
+ isTransitioningRef.current = true;
562
570
  animate(pan, toValue, index);
563
571
  if (enableHero) {
564
572
  animate(heroPan, heroToValue, index);
@@ -614,29 +622,29 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
614
622
  heroContainerLayoutRef.current = heroContainerLayout;
615
623
  }, [heroContainerLayout]);
616
624
  _react.default.useEffect(() => {
617
- pan.x.addListener(_ref4 => {
625
+ pan.x.addListener(_ref5 => {
618
626
  let {
619
627
  value
620
- } = _ref4;
628
+ } = _ref5;
621
629
  animatedX.current = value;
622
630
  });
623
- pan.y.addListener(_ref5 => {
631
+ pan.y.addListener(_ref6 => {
624
632
  let {
625
633
  value
626
- } = _ref5;
634
+ } = _ref6;
627
635
  animatedY.current = value;
628
636
  });
629
637
  if (enableHero) {
630
- heroPan.x.addListener(_ref6 => {
638
+ heroPan.x.addListener(_ref7 => {
631
639
  let {
632
640
  value
633
- } = _ref6;
641
+ } = _ref7;
634
642
  heroAnimatedX.current = value;
635
643
  });
636
- heroPan.y.addListener(_ref7 => {
644
+ heroPan.y.addListener(_ref8 => {
637
645
  let {
638
646
  value
639
- } = _ref7;
647
+ } = _ref8;
640
648
  heroAnimatedY.current = value;
641
649
  });
642
650
  }
@@ -673,7 +681,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
673
681
  stopAutoplay();
674
682
  };
675
683
  }, [stopAutoplay]);
676
- const onContainerLayout = _ref8 => {
684
+ const onContainerLayout = _ref9 => {
677
685
  let {
678
686
  nativeEvent: {
679
687
  layout: {
@@ -683,7 +691,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
683
691
  height
684
692
  }
685
693
  }
686
- } = _ref8;
694
+ } = _ref9;
687
695
  return setContainerLayout(prevState => ({
688
696
  ...prevState,
689
697
  x,
@@ -692,7 +700,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
692
700
  height
693
701
  }));
694
702
  };
695
- const onHeroContainerLayout = _ref9 => {
703
+ const onHeroContainerLayout = _ref10 => {
696
704
  let {
697
705
  nativeEvent: {
698
706
  layout: {
@@ -702,7 +710,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
702
710
  height
703
711
  }
704
712
  }
705
- } = _ref9;
713
+ } = _ref10;
706
714
  return setHeroContainerLayout(prevState => ({
707
715
  ...prevState,
708
716
  x,
@@ -711,14 +719,14 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
711
719
  height
712
720
  }));
713
721
  };
714
- const onPreviousNextNavigationButtonLayout = _ref10 => {
722
+ const onPreviousNextNavigationButtonLayout = _ref11 => {
715
723
  let {
716
724
  nativeEvent: {
717
725
  layout: {
718
726
  width
719
727
  }
720
728
  }
721
- } = _ref10;
729
+ } = _ref11;
722
730
  return setPreviousNextNavigationButtonWidth(width);
723
731
  };
724
732
  const isSwipeAllowed = _react.default.useCallback(() => {
@@ -880,6 +888,11 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
880
888
  }
881
889
  setisCarouselPlaying(prevState => !prevState);
882
890
  }, [isCarouselPlaying, stopAutoplay, startAutoplay]);
891
+ const handleKeyDown = _react.default.useCallback(event => {
892
+ if (isTransitioningRef.current && event.key === 'Tab') {
893
+ event.preventDefault();
894
+ }
895
+ }, [isTransitioningRef]);
883
896
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
884
897
  style: selectRootContainerStyles(enableHero, viewport),
885
898
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
@@ -905,6 +918,9 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
905
918
  ref: ref,
906
919
  ...systemProps,
907
920
  ...containerProps,
921
+ ...(_Platform.default.OS === 'web' ? {
922
+ onKeyDown: handleKeyDown
923
+ } : {}),
908
924
  children: [isAutoPlayEnabled ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
909
925
  style: [staticStyles.animationControlButton, selectControlButtonPositionStyles({
910
926
  positionVariant: previousNextNavigationPosition,
@@ -959,10 +975,27 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
959
975
  // This is a known Voiceover bug: https://github.com/phetsims/a11y-research/issues/132
960
976
  accessibilityLiveRegion: accessibilityLiveRegion,
961
977
  children: childrenArray.map((element, index) => {
962
- const hidden = !isAnimating && index !== activeIndex;
978
+ let hidden = !isAnimating && index !== activeIndex;
979
+ if (enablePeeking && !isAnimating) {
980
+ if (enableDisplayMultipleItemsPerSlide) {
981
+ const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
982
+ if (index >= activeIndex * maxItemsForSlide - 1 && index < activeIndex * maxItemsForSlide + maxItemsForSlide + 1) {
983
+ hidden = false;
984
+ } else {
985
+ hidden = true;
986
+ }
987
+ } else if (index >= activeIndex - 1 && index <= activeIndex + 1) {
988
+ hidden = false;
989
+ }
990
+ } else if (!enablePeeking && enableDisplayMultipleItemsPerSlide && !isAnimating) {
991
+ const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
992
+ if (index >= activeIndex * maxItemsForSlide && index < activeIndex * maxItemsForSlide + maxItemsForSlide) {
993
+ hidden = false;
994
+ }
995
+ }
963
996
  const clonedElement = /*#__PURE__*/_react.default.cloneElement(element, {
964
997
  elementIndex: index,
965
- hidden: enablePeeking || enableDisplayMultipleItemsPerSlide ? false : hidden,
998
+ hidden,
966
999
  enablePeeking,
967
1000
  peekingProps: getPeekingProps(viewport),
968
1001
  enableDisplayMultipleItemsPerSlide,
@@ -104,13 +104,33 @@ const CarouselItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
104
104
  });
105
105
  const focusabilityProps = activeIndex === elementIndex || enablePeeking ? {} : _utils.a11yProps.nonFocusableProps;
106
106
  const handleFocus = _react.default.useCallback(event => {
107
- if (_Platform.default.OS === 'web' && elementIndex >= maximumItemsForSlide * (activeIndex + 1)) {
108
- goTo(activeIndex + 1);
107
+ if (_Platform.default.OS === 'web') {
108
+ if (enablePeeking) {
109
+ if (enableDisplayMultipleItemsPerSlide) {
110
+ const startIndex = maximumItemsForSlide * activeIndex;
111
+ const endIndex = startIndex + maximumItemsForSlide - 1;
112
+ if (elementIndex < startIndex) {
113
+ if (activeIndex - 1 < 0) {
114
+ goTo(0);
115
+ } else {
116
+ goTo(activeIndex - 1);
117
+ }
118
+ } else if (elementIndex > endIndex) {
119
+ goTo(activeIndex + 1);
120
+ }
121
+ } else if (elementIndex !== activeIndex) {
122
+ if (elementIndex > activeIndex) {
123
+ goTo(activeIndex + 1);
124
+ } else if (elementIndex < activeIndex) {
125
+ goTo(activeIndex - 1);
126
+ }
127
+ }
128
+ }
109
129
  }
110
130
  if (rest.onFocus) {
111
131
  rest.onFocus(event);
112
132
  }
113
- }, [elementIndex, activeIndex, goTo, maximumItemsForSlide, rest]);
133
+ }, [elementIndex, activeIndex, goTo, maximumItemsForSlide, rest, enablePeeking, enableDisplayMultipleItemsPerSlide]);
114
134
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
115
135
  style: selectContainerStyle({
116
136
  width,
@@ -43,17 +43,14 @@ const Icon = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
43
43
  padding: themeTokens.padding
44
44
  };
45
45
  const getIconContentForMobile = () => {
46
- if (Object.keys(paddingStyles).length) {
47
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
48
- style: {
49
- backgroundColor: themeTokens.backgroundColor,
50
- borderRadius: themeTokens.borderRadius,
51
- ...paddingStyles
52
- },
53
- children: iconContent
54
- });
55
- }
56
- return iconContent;
46
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
47
+ style: {
48
+ backgroundColor: themeTokens.backgroundColor,
49
+ borderRadius: themeTokens.borderRadius,
50
+ ...paddingStyles
51
+ },
52
+ children: iconContent
53
+ });
57
54
  };
58
55
  return _Platform.default.OS === 'web' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
59
56
  ref: ref
@@ -107,7 +107,6 @@ IconText.propTypes = {
107
107
  * `<Typography>` component, or a component that renders `<Text>`.
108
108
  */
109
109
  children: _propTypes.default.node
110
- /* eslint-enable react/no-unused-prop-types */
111
110
  };
112
111
  const staticStyles = _StyleSheet.default.create({
113
112
  adjustedContainer: {
@@ -7,8 +7,8 @@ exports.default = void 0;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
10
- var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
11
10
  var _Text = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Text"));
11
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
12
12
  var _ThemeProvider = require("../ThemeProvider");
13
13
  var _Icon = _interopRequireDefault(require("../Icon"));
14
14
  var _Spacer = _interopRequireDefault(require("../Spacer"));
@@ -16,7 +16,7 @@ var _ListboxContext = require("./ListboxContext");
16
16
  var _jsxRuntime = require("react/jsx-runtime");
17
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
18
  const styles = _StyleSheet.default.create({
19
- controlWrapper: {
19
+ container: {
20
20
  width: '100%',
21
21
  flex: 1,
22
22
  alignItems: 'center',
@@ -25,6 +25,34 @@ const styles = _StyleSheet.default.create({
25
25
  boxSizing: 'border-box'
26
26
  }
27
27
  });
28
+ const selectTextStyles = tokens => ({
29
+ color: tokens.groupColor,
30
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
31
+ fontSize: tokens.groupFontSize,
32
+ fontWeight: tokens.groupFontWeight
33
+ });
34
+ const selectContainerStyles = tokens => ({
35
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
36
+ fontSize: tokens.groupFontSize,
37
+ color: tokens.groupColor,
38
+ textDecoration: tokens.itemTextDecoration,
39
+ backgroundColor: tokens.groupBackgroundColor,
40
+ outline: tokens.itemOutline,
41
+ minHeight: tokens.groupHeight,
42
+ borderRadius: tokens.groupBorderRadius,
43
+ paddingLeft: tokens.groupPaddingLeft - tokens.groupBorderLeftWidth,
44
+ paddingRight: tokens.groupPaddingRight - tokens.groupBorderRightWidth,
45
+ paddingTop: tokens.groupPaddingTop - tokens.groupBorderTopWidth,
46
+ paddingBottom: tokens.groupPaddingBottom - tokens.groupBorderBottomWidth,
47
+ borderLeftWidth: tokens.groupBorderLeftWidth,
48
+ borderLeftColor: tokens.groupBorderLeftColor,
49
+ borderRightWidth: tokens.groupBorderRightWidth,
50
+ borderRightColor: tokens.groupBorderRightColor,
51
+ borderTopWidth: tokens.groupBorderTopWidth,
52
+ borderTopColor: tokens.groupBorderTopColor,
53
+ borderBottomWidth: tokens.groupBorderBottomWidth,
54
+ borderBottomColor: tokens.groupBorderBottomColor
55
+ });
28
56
  const GroupControl = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
29
57
  let {
30
58
  expanded,
@@ -45,51 +73,17 @@ const GroupControl = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
45
73
  current: selectedId === id && id !== undefined,
46
74
  focus
47
75
  });
48
- const {
49
- groupFontName,
50
- groupFontWeight,
51
- groupFontSize,
52
- groupColor,
53
- groupBackgroundColor,
54
- groupBorderColor,
55
- groupBorderWidth,
56
- groupBorderRadius,
57
- groupPaddingLeft,
58
- groupPaddingRight,
59
- groupPaddingTop,
60
- groupPaddingBottom,
61
- itemTextDecoration,
62
- itemOutline,
63
- groupHeight
64
- } = tokens;
65
- const getTextStyles = () => ({
66
- color: groupColor
67
- });
68
76
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
69
77
  onPress: () => setSelectedId(id),
70
- style: [styles.controlWrapper, {
71
- fontFamily: `${groupFontName}${groupFontWeight}normal`,
72
- fontSize: groupFontSize,
73
- color: groupColor,
74
- textDecoration: itemTextDecoration,
75
- backgroundColor: groupBackgroundColor,
76
- outline: itemOutline,
77
- height: groupHeight,
78
- border: `${groupBorderWidth}px solid ${groupBorderColor}`,
79
- borderRadius: groupBorderRadius,
80
- paddingLeft: groupPaddingLeft - groupBorderWidth,
81
- paddingRight: groupPaddingRight - groupBorderWidth,
82
- paddingTop: groupPaddingTop - groupBorderWidth,
83
- paddingBottom: groupPaddingBottom - groupBorderWidth
84
- }],
78
+ style: [styles.container, selectContainerStyles(tokens)],
85
79
  ref: ref,
86
80
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
87
- style: getTextStyles(),
81
+ style: selectTextStyles(tokens),
88
82
  children: label
89
83
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Spacer.default, {
90
84
  space: 1,
91
85
  direction: "row"
92
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
86
+ }), tokens.groupIcon && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
93
87
  icon: tokens.groupIcon,
94
88
  tokens: {
95
89
  color: tokens.groupColor