@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
@@ -1,15 +1,16 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import View from "react-native-web/dist/exports/View";
4
- import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
4
  import Text from "react-native-web/dist/exports/Text";
5
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
6
6
  import { useThemeTokens } from '../ThemeProvider';
7
7
  import Icon from '../Icon';
8
8
  import Spacer from '../Spacer';
9
9
  import { useListboxContext } from './ListboxContext';
10
+ import { variantProp } from '../utils';
10
11
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
12
  const styles = StyleSheet.create({
12
- controlWrapper: {
13
+ container: {
13
14
  width: '100%',
14
15
  flex: 1,
15
16
  alignItems: 'center',
@@ -18,6 +19,34 @@ const styles = StyleSheet.create({
18
19
  boxSizing: 'border-box'
19
20
  }
20
21
  });
22
+ const selectTextStyles = tokens => ({
23
+ color: tokens.groupColor,
24
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
25
+ fontSize: tokens.groupFontSize,
26
+ fontWeight: tokens.groupFontWeight
27
+ });
28
+ const selectContainerStyles = tokens => ({
29
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
30
+ fontSize: tokens.groupFontSize,
31
+ color: tokens.groupColor,
32
+ textDecoration: tokens.itemTextDecoration,
33
+ backgroundColor: tokens.groupBackgroundColor,
34
+ outline: tokens.itemOutline,
35
+ minHeight: tokens.groupHeight,
36
+ borderRadius: tokens.groupBorderRadius,
37
+ paddingLeft: tokens.groupPaddingLeft - tokens.groupBorderLeftWidth,
38
+ paddingRight: tokens.groupPaddingRight - tokens.groupBorderRightWidth,
39
+ paddingTop: tokens.groupPaddingTop - tokens.groupBorderTopWidth,
40
+ paddingBottom: tokens.groupPaddingBottom - tokens.groupBorderBottomWidth,
41
+ borderLeftWidth: tokens.groupBorderLeftWidth,
42
+ borderLeftColor: tokens.groupBorderLeftColor,
43
+ borderRightWidth: tokens.groupBorderRightWidth,
44
+ borderRightColor: tokens.groupBorderRightColor,
45
+ borderTopWidth: tokens.groupBorderTopWidth,
46
+ borderTopColor: tokens.groupBorderTopColor,
47
+ borderBottomWidth: tokens.groupBorderBottomWidth,
48
+ borderBottomColor: tokens.groupBorderBottomColor
49
+ });
21
50
  const GroupControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
22
51
  let {
23
52
  expanded,
@@ -25,65 +54,35 @@ const GroupControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
25
54
  hover,
26
55
  focus,
27
56
  label,
28
- id
57
+ id,
58
+ variant = {}
29
59
  } = _ref;
30
60
  const {
31
61
  selectedId,
32
62
  setSelectedId
33
63
  } = useListboxContext();
34
- const tokens = useThemeTokens('Listbox', {}, {}, {
64
+ const isSecondLevel = variant?.secondLevel === true;
65
+ const tokens = useThemeTokens('Listbox', variant, {}, {
35
66
  expanded,
36
67
  pressed,
37
68
  hover,
38
69
  current: selectedId === id && id !== undefined,
39
- focus
40
- });
41
- const {
42
- groupFontName,
43
- groupFontWeight,
44
- groupFontSize,
45
- groupColor,
46
- groupBackgroundColor,
47
- groupBorderColor,
48
- groupBorderWidth,
49
- groupBorderRadius,
50
- groupPaddingLeft,
51
- groupPaddingRight,
52
- groupPaddingTop,
53
- groupPaddingBottom,
54
- itemTextDecoration,
55
- itemOutline,
56
- groupHeight
57
- } = tokens;
58
- const getTextStyles = () => ({
59
- color: groupColor
70
+ focus,
71
+ secondLevel: isSecondLevel
60
72
  });
73
+ const displayIcon = isSecondLevel ? tokens.secondLevelParentIcon : tokens.groupIcon;
61
74
  return /*#__PURE__*/_jsxs(View, {
62
75
  onPress: () => setSelectedId(id),
63
- style: [styles.controlWrapper, {
64
- fontFamily: `${groupFontName}${groupFontWeight}normal`,
65
- fontSize: groupFontSize,
66
- color: groupColor,
67
- textDecoration: itemTextDecoration,
68
- backgroundColor: groupBackgroundColor,
69
- outline: itemOutline,
70
- height: groupHeight,
71
- border: `${groupBorderWidth}px solid ${groupBorderColor}`,
72
- borderRadius: groupBorderRadius,
73
- paddingLeft: groupPaddingLeft - groupBorderWidth,
74
- paddingRight: groupPaddingRight - groupBorderWidth,
75
- paddingTop: groupPaddingTop - groupBorderWidth,
76
- paddingBottom: groupPaddingBottom - groupBorderWidth
77
- }],
76
+ style: [styles.container, selectContainerStyles(tokens)],
78
77
  ref: ref,
79
78
  children: [/*#__PURE__*/_jsx(Text, {
80
- style: getTextStyles(),
79
+ style: selectTextStyles(tokens),
81
80
  children: label
82
81
  }), /*#__PURE__*/_jsx(Spacer, {
83
82
  space: 1,
84
83
  direction: "row"
85
- }), /*#__PURE__*/_jsx(Icon, {
86
- icon: tokens.groupIcon,
84
+ }), displayIcon && /*#__PURE__*/_jsx(Icon, {
85
+ icon: displayIcon,
87
86
  tokens: {
88
87
  color: tokens.groupColor
89
88
  },
@@ -100,6 +99,7 @@ GroupControl.propTypes = {
100
99
  pressed: PropTypes.bool,
101
100
  hover: PropTypes.bool,
102
101
  focus: PropTypes.bool,
103
- label: PropTypes.string
102
+ label: PropTypes.string,
103
+ variant: variantProp.propType
104
104
  };
105
105
  export default GroupControl;
@@ -1,22 +1,30 @@
1
1
  import React, { createElement as _createElement } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import View from "react-native-web/dist/exports/View";
4
- import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
4
  import Platform from "react-native-web/dist/exports/Platform";
5
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
6
6
  import { useThemeTokens } from '../ThemeProvider';
7
- import { withLinkRouter, getTokensPropType } from '../utils';
7
+ import { withLinkRouter, getTokensPropType, variantProp } from '../utils';
8
8
  import ExpandCollapse from '../ExpandCollapse';
9
9
  import ListboxGroup from './ListboxGroup';
10
10
  import ListboxItem from './ListboxItem';
11
11
  import { ListboxContext } from './ListboxContext';
12
12
  import DropdownOverlay from './ListboxOverlay';
13
+ import defaultDictionary from './dictionary';
13
14
  import { jsx as _jsx } from "react/jsx-runtime";
14
15
  const styles = StyleSheet.create({
15
- list: {
16
+ container: {
16
17
  padding: 0,
17
- margin: 0
18
+ margin: 0,
19
+ position: 'relative',
20
+ overflow: 'visible'
18
21
  }
19
22
  });
23
+ const selectContainerStyles = tokens => ({
24
+ minHeight: tokens.minHeight,
25
+ minWidth: tokens.minWidth,
26
+ backgroundColor: tokens.containerBackgroundColor
27
+ });
20
28
  const getInitialOpen = (items, selectedId) => items.filter(item => item.items && item.items.some(nestedItem => (nestedItem.id ?? nestedItem.label) === selectedId)).map(item => item.id ?? item.label);
21
29
  const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
22
30
  let {
@@ -29,15 +37,16 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
29
37
  LinkRouter,
30
38
  itemRouterProps,
31
39
  onClose,
40
+ copy = 'en',
41
+ dictionary = defaultDictionary,
32
42
  variant,
33
- tokens
43
+ tokens,
44
+ testID
34
45
  } = _ref;
35
46
  const initialOpen = getInitialOpen(items, defaultSelectedId);
36
47
  const [selectedId, setSelectedId] = React.useState(defaultSelectedId);
37
- const {
38
- minHeight,
39
- minWidth
40
- } = useThemeTokens('Listbox', variant, tokens);
48
+ const [activeSecondLevelGroup, setActiveSecondLevelGroup] = React.useState(null);
49
+ const listboxTokens = useThemeTokens('Listbox', tokens, variant);
41
50
 
42
51
  // We need to keep track of each item's ref in order to be able to
43
52
  // focus on a specific item via keyboard navigation
@@ -86,21 +95,22 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
86
95
  }
87
96
  return () => {};
88
97
  }, [onClose, handleKeydown]);
98
+ const contextValue = {
99
+ selectedId,
100
+ setSelectedId,
101
+ activeSecondLevelGroup,
102
+ setActiveSecondLevelGroup
103
+ };
89
104
  return /*#__PURE__*/_jsx(ListboxContext.Provider, {
90
- value: {
91
- selectedId,
92
- setSelectedId
93
- },
105
+ value: contextValue,
94
106
  children: /*#__PURE__*/_jsx(ExpandCollapse, {
95
107
  initialOpen: initialOpen,
96
108
  maxOpen: 1,
97
109
  ref: ref,
98
110
  children: expandProps => /*#__PURE__*/_jsx(View, {
99
- style: [styles.list, {
100
- minHeight,
101
- minWidth
102
- }],
103
- role: "listbox",
111
+ style: [styles.container, selectContainerStyles(listboxTokens)],
112
+ accessibilityRole: "combobox",
113
+ testID: testID,
104
114
  children: items.map((item, index) => {
105
115
  const {
106
116
  id,
@@ -114,6 +124,9 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
114
124
  itemRefs.current[index] = currentItemRef;
115
125
  return currentItemRef;
116
126
  };
127
+ if (!nestedItems && activeSecondLevelGroup) {
128
+ return null;
129
+ }
117
130
  return nestedItems ? /*#__PURE__*/_createElement(ListboxGroup, {
118
131
  ...item,
119
132
  expandProps: expandProps,
@@ -122,7 +135,12 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
122
135
  prevItemRef: itemRefs.current[index - 1] ?? null,
123
136
  nextItemRef: itemRefs.current[index + 1] ?? null,
124
137
  ref: index === 0 ? firstItemRef : itemRef,
125
- key: itemId
138
+ key: itemId,
139
+ copy: copy,
140
+ dictionary: dictionary,
141
+ variant: variant,
142
+ tokens: tokens,
143
+ onClose: onClose
126
144
  }) : /*#__PURE__*/_createElement(ListboxItem, {
127
145
  ...item,
128
146
  key: itemId,
@@ -131,7 +149,9 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
131
149
  itemRouterProps: itemRouterProps,
132
150
  prevItemRef: itemRefs.current[index - 1] ?? null,
133
151
  nextItemRef: itemRefs.current[index + 1] ?? null,
134
- ref: index === 0 ? firstItemRef : itemRef
152
+ ref: index === 0 ? firstItemRef : itemRef,
153
+ variant: variant,
154
+ tokens: tokens
135
155
  });
136
156
  })
137
157
  })
@@ -162,7 +182,30 @@ Listbox.propTypes = {
162
182
  /**
163
183
  * onClose event
164
184
  */
165
- onClose: PropTypes.func
185
+ onClose: PropTypes.func,
186
+ /**
187
+ * Test ID for testing
188
+ */
189
+ testID: PropTypes.string,
190
+ /**
191
+ * Select English or French copy
192
+ */
193
+ copy: PropTypes.oneOf(['en', 'fr']),
194
+ /**
195
+ * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
196
+ */
197
+ dictionary: PropTypes.shape({
198
+ en: PropTypes.shape({
199
+ closeMenu: PropTypes.string.isRequired
200
+ }),
201
+ fr: PropTypes.shape({
202
+ closeMenu: PropTypes.string.isRequired
203
+ })
204
+ }),
205
+ /**
206
+ * Listbox variant
207
+ */
208
+ variant: variantProp.propType
166
209
  };
167
210
  Listbox.Overlay = DropdownOverlay;
168
211
  export default Listbox;
@@ -4,21 +4,36 @@ import PropTypes from 'prop-types';
4
4
  import View from "react-native-web/dist/exports/View";
5
5
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
6
6
  import Platform from "react-native-web/dist/exports/Platform";
7
- import { withLinkRouter } from '../utils';
7
+ import { withLinkRouter, variantProp, copyPropTypes } from '../utils';
8
+ import { useThemeTokens } from '../ThemeProvider';
8
9
  import ExpandCollapse from '../ExpandCollapse';
9
10
  import ListboxItem from './ListboxItem';
10
11
  import { useListboxContext } from './ListboxContext';
11
12
  import GroupControl from './GroupControl';
12
- import { jsx as _jsx } from "react/jsx-runtime";
13
+ import SecondLevelHeader from './SecondLevelHeader';
14
+ import defaultDictionary from './dictionary';
15
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
16
  const styles = StyleSheet.create({
14
17
  groupWrapper: {
15
18
  margin: 0,
16
19
  padding: 0,
17
- overflow: 'hidden'
20
+ overflow: 'visible'
18
21
  },
19
22
  list: {
20
23
  margin: 0,
21
24
  padding: 0
25
+ },
26
+ secondLevelContainer: {
27
+ margin: 0,
28
+ padding: 0,
29
+ width: '100%',
30
+ display: 'flex',
31
+ flexDirection: 'column'
32
+ },
33
+ secondLevelList: {
34
+ margin: 0,
35
+ padding: 0,
36
+ width: '100%'
22
37
  }
23
38
  });
24
39
  const getAccessibilityRole = () => Platform.select({
@@ -26,7 +41,15 @@ const getAccessibilityRole = () => Platform.select({
26
41
  android: 'none',
27
42
  web: 'listitem'
28
43
  });
29
- const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
44
+ const selectSecondLevelContainerStyles = _ref => {
45
+ let {
46
+ secondLevelHeaderBackgroundColor
47
+ } = _ref;
48
+ return {
49
+ backgroundColor: secondLevelHeaderBackgroundColor
50
+ };
51
+ };
52
+ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
30
53
  let {
31
54
  id,
32
55
  label,
@@ -36,11 +59,79 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
36
59
  expandProps,
37
60
  onLastItemBlur,
38
61
  nextItemRef,
39
- prevItemRef
40
- } = _ref;
62
+ prevItemRef,
63
+ copy = 'en',
64
+ dictionary = defaultDictionary,
65
+ variant = {},
66
+ tokens = {},
67
+ onClose
68
+ } = _ref2;
41
69
  const {
42
- selectedId
70
+ selectedId,
71
+ activeSecondLevelGroup,
72
+ setActiveSecondLevelGroup
43
73
  } = useListboxContext();
74
+ const [secondLevelOpen, setSecondLevelOpen] = React.useState(false);
75
+ const isSecondLevel = variant?.secondLevel === true;
76
+ const listboxTokens = useThemeTokens('Listbox', variant, tokens);
77
+ const groupId = id ?? label;
78
+ const handleGroupClick = React.useCallback(() => {
79
+ if (isSecondLevel) {
80
+ setSecondLevelOpen(true);
81
+ setActiveSecondLevelGroup(groupId);
82
+ }
83
+ }, [isSecondLevel, groupId, setActiveSecondLevelGroup]);
84
+ const handleBackClick = React.useCallback(() => {
85
+ setSecondLevelOpen(false);
86
+ setActiveSecondLevelGroup(null);
87
+ }, [setActiveSecondLevelGroup]);
88
+ const handleCloseClick = React.useCallback(() => {
89
+ setSecondLevelOpen(false);
90
+ setActiveSecondLevelGroup(null);
91
+ if (onClose) {
92
+ onClose();
93
+ }
94
+ }, [setActiveSecondLevelGroup, onClose]);
95
+ if (isSecondLevel && activeSecondLevelGroup && activeSecondLevelGroup !== groupId) {
96
+ return null;
97
+ }
98
+ if (isSecondLevel && secondLevelOpen) {
99
+ return /*#__PURE__*/_jsxs(View, {
100
+ style: [styles.secondLevelContainer, selectSecondLevelContainerStyles(listboxTokens)],
101
+ children: [/*#__PURE__*/_jsx(SecondLevelHeader, {
102
+ label: label,
103
+ onBack: handleBackClick,
104
+ onClose: handleCloseClick,
105
+ copy: copy,
106
+ dictionary: dictionary,
107
+ variant: variant,
108
+ tokens: tokens
109
+ }), /*#__PURE__*/_jsx(View, {
110
+ style: styles.secondLevelList,
111
+ children: items && items.map((item, index) => {
112
+ return /*#__PURE__*/_jsx(ListboxItem, {
113
+ id: item.id ?? item.label,
114
+ ...item,
115
+ selected: item.id && item.id === selectedId || item.label && item.label === selectedId,
116
+ isChild: false,
117
+ LinkRouter: LinkRouter,
118
+ linkRouterProps: linkRouterProps,
119
+ variant: variant,
120
+ tokens: tokens,
121
+ ...(index === 0 && {
122
+ prevItemRef
123
+ }),
124
+ ...(index === items.length - 1 && {
125
+ nextItemRef
126
+ }),
127
+ ...(index === items.length - 1 && {
128
+ onBlur: onLastItemBlur
129
+ })
130
+ }, item.label);
131
+ })
132
+ })]
133
+ });
134
+ }
44
135
 
45
136
  // TODO: implement keyboard navigation via refs for grouped items separately here
46
137
  return /*#__PURE__*/_jsx(View, {
@@ -66,9 +157,16 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
66
157
  control: controlProps => /*#__PURE__*/_jsx(GroupControl, {
67
158
  id: id ?? label,
68
159
  ...controlProps,
69
- label: label
160
+ label: label,
161
+ variant: variant
70
162
  }),
71
163
  ...expandProps,
164
+ ...(isSecondLevel && {
165
+ open: false
166
+ }),
167
+ ...(isSecondLevel && {
168
+ onPress: handleGroupClick
169
+ }),
72
170
  tokens: {
73
171
  contentPaddingLeft: 0,
74
172
  contentPaddingRight: 0,
@@ -77,10 +175,11 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
77
175
  borderColor: 'transparent',
78
176
  borderRadius: 0,
79
177
  borderWidth: 0,
80
- marginBottom: 0
178
+ marginBottom: 0,
179
+ contentPanelBackgroundColor: 'transparent'
81
180
  },
82
181
  controlRef: ref,
83
- children: /*#__PURE__*/_jsx(View, {
182
+ children: !isSecondLevel && /*#__PURE__*/_jsx(View, {
84
183
  style: styles.list,
85
184
  children: items.map((item, index) => {
86
185
  return /*#__PURE__*/_jsx(ListboxItem, {
@@ -90,6 +189,8 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
90
189
  isChild: true,
91
190
  LinkRouter: LinkRouter,
92
191
  linkRouterProps: linkRouterProps,
192
+ variant: variant,
193
+ tokens: tokens,
93
194
  ...(index === 0 && {
94
195
  prevItemRef
95
196
  }),
@@ -108,6 +209,10 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
108
209
  ListboxGroup.displayName = 'ListboxGroup';
109
210
  ListboxGroup.propTypes = {
110
211
  ...withLinkRouter.propTypes,
212
+ /**
213
+ * Unique identifier for the group
214
+ */
215
+ id: PropTypes.string,
111
216
  label: PropTypes.string,
112
217
  items: PropTypes.arrayOf(PropTypes.shape({
113
218
  href: PropTypes.string,
@@ -120,6 +225,33 @@ ListboxGroup.propTypes = {
120
225
  /**
121
226
  * Use this callback to redirect the focus after it leaves the last item of the group.
122
227
  */
123
- onLastItemBlur: PropTypes.func
228
+ onLastItemBlur: PropTypes.func,
229
+ /**
230
+ * Select English or French copy
231
+ */
232
+ copy: copyPropTypes,
233
+ /**
234
+ * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
235
+ */
236
+ dictionary: PropTypes.shape({
237
+ en: PropTypes.shape({
238
+ closeMenu: PropTypes.string.isRequired
239
+ }),
240
+ fr: PropTypes.shape({
241
+ closeMenu: PropTypes.string.isRequired
242
+ })
243
+ }),
244
+ /**
245
+ * Variant configuration for secondLevel behavior
246
+ */
247
+ variant: variantProp.propType,
248
+ /**
249
+ * Custom tokens
250
+ */
251
+ tokens: PropTypes.object,
252
+ /**
253
+ * Callback when the menu is closed
254
+ */
255
+ onClose: PropTypes.func
124
256
  };
125
257
  export default ListboxGroup;
@@ -30,12 +30,15 @@ const DropdownOverlay = /*#__PURE__*/React.forwardRef((_ref, ref) => {
30
30
  maxWidth,
31
31
  minWidth,
32
32
  onLayout,
33
- tokens
33
+ tokens,
34
+ testID,
35
+ variant
34
36
  } = _ref;
35
- const systemTokens = useThemeTokens('Listbox', {}, {});
37
+ const systemTokens = useThemeTokens('Listbox', variant, tokens);
36
38
  return /*#__PURE__*/_jsx(View, {
37
39
  ref: ref,
38
40
  onLayout: onLayout,
41
+ testID: testID,
39
42
  style: [overlaidPosition, {
40
43
  maxWidth,
41
44
  minWidth
@@ -43,11 +46,14 @@ const DropdownOverlay = /*#__PURE__*/React.forwardRef((_ref, ref) => {
43
46
  children: /*#__PURE__*/_jsx(Card, {
44
47
  tokens: {
45
48
  shadow: systemTokens.shadow,
49
+ borderRadius: systemTokens.borderRadius,
50
+ ...(Platform.OS === 'web' && {
51
+ overflowY: 'hidden'
52
+ }),
46
53
  paddingBottom: paddingVertical,
47
54
  paddingTop: paddingVertical,
48
55
  paddingLeft: paddingHorizontal,
49
- paddingRight: paddingHorizontal,
50
- ...tokens
56
+ paddingRight: paddingHorizontal
51
57
  },
52
58
  children: children
53
59
  })
@@ -74,6 +80,8 @@ DropdownOverlay.propTypes = {
74
80
  maxWidth: PropTypes.number,
75
81
  minWidth: PropTypes.number,
76
82
  onLayout: PropTypes.func,
77
- tokens: PropTypes.object
83
+ tokens: PropTypes.object,
84
+ testID: PropTypes.string,
85
+ variant: PropTypes.object
78
86
  };
79
87
  export default Platform.OS === 'web' ? withPortal(DropdownOverlay) : DropdownOverlay;
@@ -41,10 +41,14 @@ const getItemStyles = _ref => {
41
41
  color: itemColor,
42
42
  outline: itemOutline,
43
43
  textDecoration: itemTextDecoration,
44
- borderLeft: `${itemBorderLeftWidth}px solid ${itemBorderLeftColor}`,
45
- borderRight: `${itemBorderRightWidth}px solid ${itemBorderRightColor}`,
46
- borderTop: `${itemBorderTopWidth}px solid ${itemBorderTopColor}`,
47
- borderBottom: `${itemBorderBottomWidth}px solid ${itemBorderBottomColor}`,
44
+ borderLeftWidth: itemBorderLeftWidth,
45
+ borderLeftColor: itemBorderLeftColor,
46
+ borderRightWidth: itemBorderRightWidth,
47
+ borderRightColor: itemBorderRightColor,
48
+ borderTopWidth: itemBorderTopWidth,
49
+ borderTopColor: itemBorderTopColor,
50
+ borderBottomWidth: itemBorderBottomWidth,
51
+ borderBottomColor: itemBorderBottomColor,
48
52
  borderRadius: itemBorderRadius,
49
53
  justifyContent: 'center'
50
54
  };