@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.
- package/CHANGELOG.md +29 -1
- package/lib/cjs/Button/Button.js +2 -0
- package/lib/cjs/Button/ButtonBase.js +10 -5
- package/lib/cjs/Button/ButtonDropdown.js +2 -0
- package/lib/cjs/Button/ButtonGroup.js +45 -38
- package/lib/cjs/Button/propTypes.js +6 -0
- package/lib/cjs/Card/CardBase.js +97 -17
- package/lib/cjs/Card/PressableCardBase.js +12 -8
- package/lib/cjs/Carousel/Carousel.js +52 -19
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +23 -3
- package/lib/cjs/HorizontalScroll/HorizontalScroll.js +5 -2
- package/lib/cjs/Icon/Icon.js +11 -11
- package/lib/cjs/Icon/IconText.js +0 -1
- package/lib/cjs/Listbox/GroupControl.js +44 -44
- package/lib/cjs/Listbox/Listbox.js +63 -20
- package/lib/cjs/Listbox/ListboxGroup.js +141 -9
- package/lib/cjs/Listbox/ListboxOverlay.js +13 -5
- package/lib/cjs/Listbox/PressableItem.js +8 -4
- package/lib/cjs/Listbox/SecondLevelHeader.js +201 -0
- package/lib/cjs/Listbox/dictionary.js +14 -0
- package/lib/cjs/Shortcuts/Shortcuts.js +169 -0
- package/lib/cjs/Shortcuts/ShortcutsItem.js +280 -0
- package/lib/cjs/Shortcuts/index.js +16 -0
- package/lib/cjs/TextInput/TextInputBase.js +5 -1
- package/lib/cjs/Tooltip/Tooltip.native.js +2 -0
- package/lib/cjs/Validator/Validator.js +171 -135
- package/lib/cjs/index.js +15 -0
- package/lib/esm/Button/Button.js +2 -0
- package/lib/esm/Button/ButtonBase.js +10 -5
- package/lib/esm/Button/ButtonDropdown.js +2 -0
- package/lib/esm/Button/ButtonGroup.js +44 -39
- package/lib/esm/Button/propTypes.js +6 -0
- package/lib/esm/Card/CardBase.js +97 -17
- package/lib/esm/Card/PressableCardBase.js +10 -8
- package/lib/esm/Carousel/Carousel.js +52 -19
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +23 -3
- package/lib/esm/HorizontalScroll/HorizontalScroll.js +6 -3
- package/lib/esm/Icon/Icon.js +11 -11
- package/lib/esm/Icon/IconText.js +0 -1
- package/lib/esm/Listbox/GroupControl.js +44 -44
- package/lib/esm/Listbox/Listbox.js +64 -21
- package/lib/esm/Listbox/ListboxGroup.js +143 -11
- package/lib/esm/Listbox/ListboxOverlay.js +13 -5
- package/lib/esm/Listbox/PressableItem.js +8 -4
- package/lib/esm/Listbox/SecondLevelHeader.js +194 -0
- package/lib/esm/Listbox/dictionary.js +8 -0
- package/lib/esm/Shortcuts/Shortcuts.js +160 -0
- package/lib/esm/Shortcuts/ShortcutsItem.js +273 -0
- package/lib/esm/Shortcuts/index.js +3 -0
- package/lib/esm/TextInput/TextInputBase.js +5 -1
- package/lib/esm/Tooltip/Tooltip.native.js +2 -0
- package/lib/esm/Validator/Validator.js +171 -135
- package/lib/esm/index.js +1 -0
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Button/Button.jsx +2 -1
- package/src/Button/ButtonBase.jsx +18 -12
- package/src/Button/ButtonDropdown.jsx +2 -0
- package/src/Button/ButtonGroup.jsx +62 -45
- package/src/Button/propTypes.js +6 -0
- package/src/Card/CardBase.jsx +113 -14
- package/src/Card/PressableCardBase.jsx +17 -5
- package/src/Carousel/Carousel.jsx +58 -5
- package/src/Carousel/CarouselItem/CarouselItem.jsx +31 -3
- package/src/HorizontalScroll/HorizontalScroll.jsx +6 -3
- package/src/Icon/Icon.jsx +14 -14
- package/src/Icon/IconText.jsx +0 -1
- package/src/Listbox/GroupControl.jsx +72 -70
- package/src/Listbox/Listbox.jsx +67 -11
- package/src/Listbox/ListboxGroup.jsx +160 -27
- package/src/Listbox/ListboxOverlay.jsx +23 -5
- package/src/Listbox/PressableItem.jsx +8 -4
- package/src/Listbox/SecondLevelHeader.jsx +182 -0
- package/src/Listbox/dictionary.js +8 -0
- package/src/Shortcuts/Shortcuts.jsx +174 -0
- package/src/Shortcuts/ShortcutsItem.jsx +297 -0
- package/src/Shortcuts/index.js +4 -0
- package/src/TextInput/TextInputBase.jsx +5 -1
- package/src/Tooltip/Tooltip.native.jsx +2 -1
- package/src/Validator/Validator.jsx +180 -159
- package/src/index.js +1 -0
- package/types/Listbox.d.ts +24 -0
- package/types/Shortcuts.d.ts +136 -0
- 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
|
-
|
|
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
|
|
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.
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
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: '
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
};
|