@telus-uds/components-base 3.22.0 → 3.24.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 (84) hide show
  1. package/CHANGELOG.md +29 -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/Card/CardBase.js +97 -17
  8. package/lib/cjs/Card/PressableCardBase.js +12 -8
  9. package/lib/cjs/Carousel/Carousel.js +52 -19
  10. package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +23 -3
  11. package/lib/cjs/HorizontalScroll/HorizontalScroll.js +5 -2
  12. package/lib/cjs/Icon/Icon.js +11 -11
  13. package/lib/cjs/Icon/IconText.js +0 -1
  14. package/lib/cjs/Listbox/GroupControl.js +44 -44
  15. package/lib/cjs/Listbox/Listbox.js +63 -20
  16. package/lib/cjs/Listbox/ListboxGroup.js +141 -9
  17. package/lib/cjs/Listbox/ListboxOverlay.js +13 -5
  18. package/lib/cjs/Listbox/PressableItem.js +8 -4
  19. package/lib/cjs/Listbox/SecondLevelHeader.js +201 -0
  20. package/lib/cjs/Listbox/dictionary.js +14 -0
  21. package/lib/cjs/Shortcuts/Shortcuts.js +169 -0
  22. package/lib/cjs/Shortcuts/ShortcutsItem.js +280 -0
  23. package/lib/cjs/Shortcuts/index.js +16 -0
  24. package/lib/cjs/TextInput/TextInputBase.js +5 -1
  25. package/lib/cjs/Tooltip/Tooltip.native.js +2 -0
  26. package/lib/cjs/Validator/Validator.js +171 -135
  27. package/lib/cjs/index.js +15 -0
  28. package/lib/esm/Button/Button.js +2 -0
  29. package/lib/esm/Button/ButtonBase.js +10 -5
  30. package/lib/esm/Button/ButtonDropdown.js +2 -0
  31. package/lib/esm/Button/ButtonGroup.js +44 -39
  32. package/lib/esm/Button/propTypes.js +6 -0
  33. package/lib/esm/Card/CardBase.js +97 -17
  34. package/lib/esm/Card/PressableCardBase.js +10 -8
  35. package/lib/esm/Carousel/Carousel.js +52 -19
  36. package/lib/esm/Carousel/CarouselItem/CarouselItem.js +23 -3
  37. package/lib/esm/HorizontalScroll/HorizontalScroll.js +6 -3
  38. package/lib/esm/Icon/Icon.js +11 -11
  39. package/lib/esm/Icon/IconText.js +0 -1
  40. package/lib/esm/Listbox/GroupControl.js +44 -44
  41. package/lib/esm/Listbox/Listbox.js +64 -21
  42. package/lib/esm/Listbox/ListboxGroup.js +143 -11
  43. package/lib/esm/Listbox/ListboxOverlay.js +13 -5
  44. package/lib/esm/Listbox/PressableItem.js +8 -4
  45. package/lib/esm/Listbox/SecondLevelHeader.js +194 -0
  46. package/lib/esm/Listbox/dictionary.js +8 -0
  47. package/lib/esm/Shortcuts/Shortcuts.js +160 -0
  48. package/lib/esm/Shortcuts/ShortcutsItem.js +273 -0
  49. package/lib/esm/Shortcuts/index.js +3 -0
  50. package/lib/esm/TextInput/TextInputBase.js +5 -1
  51. package/lib/esm/Tooltip/Tooltip.native.js +2 -0
  52. package/lib/esm/Validator/Validator.js +171 -135
  53. package/lib/esm/index.js +1 -0
  54. package/lib/package.json +2 -2
  55. package/package.json +2 -2
  56. package/src/Button/Button.jsx +2 -1
  57. package/src/Button/ButtonBase.jsx +18 -12
  58. package/src/Button/ButtonDropdown.jsx +2 -0
  59. package/src/Button/ButtonGroup.jsx +62 -45
  60. package/src/Button/propTypes.js +6 -0
  61. package/src/Card/CardBase.jsx +113 -14
  62. package/src/Card/PressableCardBase.jsx +17 -5
  63. package/src/Carousel/Carousel.jsx +58 -5
  64. package/src/Carousel/CarouselItem/CarouselItem.jsx +31 -3
  65. package/src/HorizontalScroll/HorizontalScroll.jsx +6 -3
  66. package/src/Icon/Icon.jsx +14 -14
  67. package/src/Icon/IconText.jsx +0 -1
  68. package/src/Listbox/GroupControl.jsx +72 -70
  69. package/src/Listbox/Listbox.jsx +67 -11
  70. package/src/Listbox/ListboxGroup.jsx +160 -27
  71. package/src/Listbox/ListboxOverlay.jsx +23 -5
  72. package/src/Listbox/PressableItem.jsx +8 -4
  73. package/src/Listbox/SecondLevelHeader.jsx +182 -0
  74. package/src/Listbox/dictionary.js +8 -0
  75. package/src/Shortcuts/Shortcuts.jsx +174 -0
  76. package/src/Shortcuts/ShortcutsItem.jsx +297 -0
  77. package/src/Shortcuts/index.js +4 -0
  78. package/src/TextInput/TextInputBase.jsx +5 -1
  79. package/src/Tooltip/Tooltip.native.jsx +2 -1
  80. package/src/Validator/Validator.jsx +180 -159
  81. package/src/index.js +1 -0
  82. package/types/Listbox.d.ts +24 -0
  83. package/types/Shortcuts.d.ts +136 -0
  84. package/types/index.d.ts +12 -0
@@ -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,
@@ -35,6 +35,7 @@ const HorizontalScroll = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
35
35
  ScrollButton,
36
36
  tokens,
37
37
  itemPositions,
38
+ variant,
38
39
  children,
39
40
  ...rest
40
41
  } = _ref;
@@ -78,8 +79,9 @@ const HorizontalScroll = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
78
79
  setScrollOffset(x);
79
80
  };
80
81
  const scrollMax = Math.max(0, contentWidth - containerWidth);
81
- const showNextButton = scrollOffset < scrollMax;
82
- const showPreviousButton = scrollOffset > 0;
82
+ const hideNavigationButtons = variant?.hideNavigationButtons || false;
83
+ const showNextButton = scrollOffset < scrollMax && !hideNavigationButtons;
84
+ const showPreviousButton = scrollOffset > 0 && !hideNavigationButtons;
83
85
  const scrollRef = _react.default.useRef(null);
84
86
  const scrollTo = targetX => {
85
87
  if (typeof scrollRef.current?.scrollTo === 'function') {
@@ -170,6 +172,7 @@ HorizontalScroll.propTypes = {
170
172
  tokens: (0, _utils.getTokensSetPropType)(tokenKeys, {
171
173
  allowFunction: true
172
174
  }),
175
+ variant: _utils.variantProp.propType,
173
176
  children: _propTypes.default.node
174
177
  };
175
178
  var _default = exports.default = HorizontalScroll;
@@ -21,6 +21,7 @@ const Icon = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
21
21
  tokens,
22
22
  scalesWithText = false,
23
23
  style = {},
24
+ testID,
24
25
  dataSet
25
26
  } = _ref;
26
27
  const themeTokens = (0, _ThemeProvider.useThemeTokens)('Icon', tokens, variant);
@@ -43,19 +44,18 @@ const Icon = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
43
44
  padding: themeTokens.padding
44
45
  };
45
46
  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;
47
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
48
+ testID: testID,
49
+ style: {
50
+ backgroundColor: themeTokens.backgroundColor,
51
+ borderRadius: themeTokens.borderRadius,
52
+ ...paddingStyles
53
+ },
54
+ children: iconContent
55
+ });
57
56
  };
58
57
  return _Platform.default.OS === 'web' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
58
+ testID: testID,
59
59
  ref: ref
60
60
  // eslint-disable-next-line react-native/no-inline-styles
61
61
  ,
@@ -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,16 +7,17 @@ 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"));
15
15
  var _ListboxContext = require("./ListboxContext");
16
+ var _utils = require("../utils");
16
17
  var _jsxRuntime = require("react/jsx-runtime");
17
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
19
  const styles = _StyleSheet.default.create({
19
- controlWrapper: {
20
+ container: {
20
21
  width: '100%',
21
22
  flex: 1,
22
23
  alignItems: 'center',
@@ -25,6 +26,34 @@ const styles = _StyleSheet.default.create({
25
26
  boxSizing: 'border-box'
26
27
  }
27
28
  });
29
+ const selectTextStyles = tokens => ({
30
+ color: tokens.groupColor,
31
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
32
+ fontSize: tokens.groupFontSize,
33
+ fontWeight: tokens.groupFontWeight
34
+ });
35
+ const selectContainerStyles = tokens => ({
36
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
37
+ fontSize: tokens.groupFontSize,
38
+ color: tokens.groupColor,
39
+ textDecoration: tokens.itemTextDecoration,
40
+ backgroundColor: tokens.groupBackgroundColor,
41
+ outline: tokens.itemOutline,
42
+ minHeight: tokens.groupHeight,
43
+ borderRadius: tokens.groupBorderRadius,
44
+ paddingLeft: tokens.groupPaddingLeft - tokens.groupBorderLeftWidth,
45
+ paddingRight: tokens.groupPaddingRight - tokens.groupBorderRightWidth,
46
+ paddingTop: tokens.groupPaddingTop - tokens.groupBorderTopWidth,
47
+ paddingBottom: tokens.groupPaddingBottom - tokens.groupBorderBottomWidth,
48
+ borderLeftWidth: tokens.groupBorderLeftWidth,
49
+ borderLeftColor: tokens.groupBorderLeftColor,
50
+ borderRightWidth: tokens.groupBorderRightWidth,
51
+ borderRightColor: tokens.groupBorderRightColor,
52
+ borderTopWidth: tokens.groupBorderTopWidth,
53
+ borderTopColor: tokens.groupBorderTopColor,
54
+ borderBottomWidth: tokens.groupBorderBottomWidth,
55
+ borderBottomColor: tokens.groupBorderBottomColor
56
+ });
28
57
  const GroupControl = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
29
58
  let {
30
59
  expanded,
@@ -32,65 +61,35 @@ const GroupControl = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
32
61
  hover,
33
62
  focus,
34
63
  label,
35
- id
64
+ id,
65
+ variant = {}
36
66
  } = _ref;
37
67
  const {
38
68
  selectedId,
39
69
  setSelectedId
40
70
  } = (0, _ListboxContext.useListboxContext)();
41
- const tokens = (0, _ThemeProvider.useThemeTokens)('Listbox', {}, {}, {
71
+ const isSecondLevel = variant?.secondLevel === true;
72
+ const tokens = (0, _ThemeProvider.useThemeTokens)('Listbox', variant, {}, {
42
73
  expanded,
43
74
  pressed,
44
75
  hover,
45
76
  current: selectedId === id && id !== undefined,
46
- focus
47
- });
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
77
+ focus,
78
+ secondLevel: isSecondLevel
67
79
  });
80
+ const displayIcon = isSecondLevel ? tokens.secondLevelParentIcon : tokens.groupIcon;
68
81
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
69
82
  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
- }],
83
+ style: [styles.container, selectContainerStyles(tokens)],
85
84
  ref: ref,
86
85
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
87
- style: getTextStyles(),
86
+ style: selectTextStyles(tokens),
88
87
  children: label
89
88
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Spacer.default, {
90
89
  space: 1,
91
90
  direction: "row"
92
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
93
- icon: tokens.groupIcon,
91
+ }), displayIcon && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
92
+ icon: displayIcon,
94
93
  tokens: {
95
94
  color: tokens.groupColor
96
95
  },
@@ -107,6 +106,7 @@ GroupControl.propTypes = {
107
106
  pressed: _propTypes.default.bool,
108
107
  hover: _propTypes.default.bool,
109
108
  focus: _propTypes.default.bool,
110
- label: _propTypes.default.string
109
+ label: _propTypes.default.string,
110
+ variant: _utils.variantProp.propType
111
111
  };
112
112
  var _default = exports.default = GroupControl;
@@ -7,8 +7,8 @@ exports.default = void 0;
7
7
  var _react = _interopRequireWildcard(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 _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
11
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
12
12
  var _ThemeProvider = require("../ThemeProvider");
13
13
  var _utils = require("../utils");
14
14
  var _ExpandCollapse = _interopRequireDefault(require("../ExpandCollapse"));
@@ -16,16 +16,24 @@ var _ListboxGroup = _interopRequireDefault(require("./ListboxGroup"));
16
16
  var _ListboxItem = _interopRequireDefault(require("./ListboxItem"));
17
17
  var _ListboxContext = require("./ListboxContext");
18
18
  var _ListboxOverlay = _interopRequireDefault(require("./ListboxOverlay"));
19
+ var _dictionary = _interopRequireDefault(require("./dictionary"));
19
20
  var _jsxRuntime = require("react/jsx-runtime");
20
21
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
21
22
  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
23
  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; }
23
24
  const styles = _StyleSheet.default.create({
24
- list: {
25
+ container: {
25
26
  padding: 0,
26
- margin: 0
27
+ margin: 0,
28
+ position: 'relative',
29
+ overflow: 'visible'
27
30
  }
28
31
  });
32
+ const selectContainerStyles = tokens => ({
33
+ minHeight: tokens.minHeight,
34
+ minWidth: tokens.minWidth,
35
+ backgroundColor: tokens.containerBackgroundColor
36
+ });
29
37
  const getInitialOpen = (items, selectedId) => items.filter(item => item.items && item.items.some(nestedItem => (nestedItem.id ?? nestedItem.label) === selectedId)).map(item => item.id ?? item.label);
30
38
  const Listbox = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
31
39
  let {
@@ -38,15 +46,16 @@ const Listbox = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
38
46
  LinkRouter,
39
47
  itemRouterProps,
40
48
  onClose,
49
+ copy = 'en',
50
+ dictionary = _dictionary.default,
41
51
  variant,
42
- tokens
52
+ tokens,
53
+ testID
43
54
  } = _ref;
44
55
  const initialOpen = getInitialOpen(items, defaultSelectedId);
45
56
  const [selectedId, setSelectedId] = _react.default.useState(defaultSelectedId);
46
- const {
47
- minHeight,
48
- minWidth
49
- } = (0, _ThemeProvider.useThemeTokens)('Listbox', variant, tokens);
57
+ const [activeSecondLevelGroup, setActiveSecondLevelGroup] = _react.default.useState(null);
58
+ const listboxTokens = (0, _ThemeProvider.useThemeTokens)('Listbox', tokens, variant);
50
59
 
51
60
  // We need to keep track of each item's ref in order to be able to
52
61
  // focus on a specific item via keyboard navigation
@@ -95,21 +104,22 @@ const Listbox = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
95
104
  }
96
105
  return () => {};
97
106
  }, [onClose, handleKeydown]);
107
+ const contextValue = {
108
+ selectedId,
109
+ setSelectedId,
110
+ activeSecondLevelGroup,
111
+ setActiveSecondLevelGroup
112
+ };
98
113
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ListboxContext.ListboxContext.Provider, {
99
- value: {
100
- selectedId,
101
- setSelectedId
102
- },
114
+ value: contextValue,
103
115
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ExpandCollapse.default, {
104
116
  initialOpen: initialOpen,
105
117
  maxOpen: 1,
106
118
  ref: ref,
107
119
  children: expandProps => /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
108
- style: [styles.list, {
109
- minHeight,
110
- minWidth
111
- }],
112
- role: "listbox",
120
+ style: [styles.container, selectContainerStyles(listboxTokens)],
121
+ accessibilityRole: "combobox",
122
+ testID: testID,
113
123
  children: items.map((item, index) => {
114
124
  const {
115
125
  id,
@@ -123,6 +133,9 @@ const Listbox = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
123
133
  itemRefs.current[index] = currentItemRef;
124
134
  return currentItemRef;
125
135
  };
136
+ if (!nestedItems && activeSecondLevelGroup) {
137
+ return null;
138
+ }
126
139
  return nestedItems ? /*#__PURE__*/(0, _react.createElement)(_ListboxGroup.default, {
127
140
  ...item,
128
141
  expandProps: expandProps,
@@ -131,7 +144,12 @@ const Listbox = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
131
144
  prevItemRef: itemRefs.current[index - 1] ?? null,
132
145
  nextItemRef: itemRefs.current[index + 1] ?? null,
133
146
  ref: index === 0 ? firstItemRef : itemRef,
134
- key: itemId
147
+ key: itemId,
148
+ copy: copy,
149
+ dictionary: dictionary,
150
+ variant: variant,
151
+ tokens: tokens,
152
+ onClose: onClose
135
153
  }) : /*#__PURE__*/(0, _react.createElement)(_ListboxItem.default, {
136
154
  ...item,
137
155
  key: itemId,
@@ -140,7 +158,9 @@ const Listbox = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
140
158
  itemRouterProps: itemRouterProps,
141
159
  prevItemRef: itemRefs.current[index - 1] ?? null,
142
160
  nextItemRef: itemRefs.current[index + 1] ?? null,
143
- ref: index === 0 ? firstItemRef : itemRef
161
+ ref: index === 0 ? firstItemRef : itemRef,
162
+ variant: variant,
163
+ tokens: tokens
144
164
  });
145
165
  })
146
166
  })
@@ -171,7 +191,30 @@ Listbox.propTypes = {
171
191
  /**
172
192
  * onClose event
173
193
  */
174
- onClose: _propTypes.default.func
194
+ onClose: _propTypes.default.func,
195
+ /**
196
+ * Test ID for testing
197
+ */
198
+ testID: _propTypes.default.string,
199
+ /**
200
+ * Select English or French copy
201
+ */
202
+ copy: _propTypes.default.oneOf(['en', 'fr']),
203
+ /**
204
+ * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
205
+ */
206
+ dictionary: _propTypes.default.shape({
207
+ en: _propTypes.default.shape({
208
+ closeMenu: _propTypes.default.string.isRequired
209
+ }),
210
+ fr: _propTypes.default.shape({
211
+ closeMenu: _propTypes.default.string.isRequired
212
+ })
213
+ }),
214
+ /**
215
+ * Listbox variant
216
+ */
217
+ variant: _utils.variantProp.propType
175
218
  };
176
219
  Listbox.Overlay = _ListboxOverlay.default;
177
220
  var _default = exports.default = Listbox;