@telus-uds/components-base 3.23.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 +12 -1
- package/lib/cjs/Card/CardBase.js +97 -17
- package/lib/cjs/Card/PressableCardBase.js +12 -8
- package/lib/cjs/HorizontalScroll/HorizontalScroll.js +5 -2
- package/lib/cjs/Icon/Icon.js +3 -0
- package/lib/cjs/Listbox/GroupControl.js +12 -6
- package/lib/cjs/Listbox/Listbox.js +41 -7
- package/lib/cjs/Listbox/ListboxGroup.js +139 -8
- package/lib/cjs/Listbox/ListboxOverlay.js +10 -5
- 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/Tooltip/Tooltip.native.js +2 -0
- package/lib/cjs/index.js +15 -0
- package/lib/esm/Card/CardBase.js +97 -17
- package/lib/esm/Card/PressableCardBase.js +10 -8
- package/lib/esm/HorizontalScroll/HorizontalScroll.js +6 -3
- package/lib/esm/Icon/Icon.js +3 -0
- package/lib/esm/Listbox/GroupControl.js +12 -6
- package/lib/esm/Listbox/Listbox.js +41 -7
- package/lib/esm/Listbox/ListboxGroup.js +141 -10
- package/lib/esm/Listbox/ListboxOverlay.js +10 -5
- 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/Tooltip/Tooltip.native.js +2 -0
- package/lib/esm/index.js +1 -0
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Card/CardBase.jsx +113 -14
- package/src/Card/PressableCardBase.jsx +17 -5
- package/src/HorizontalScroll/HorizontalScroll.jsx +6 -3
- package/src/Icon/Icon.jsx +3 -0
- package/src/Listbox/GroupControl.jsx +41 -33
- package/src/Listbox/Listbox.jsx +41 -2
- package/src/Listbox/ListboxGroup.jsx +158 -26
- package/src/Listbox/ListboxOverlay.jsx +18 -5
- 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/Tooltip/Tooltip.native.jsx +2 -1
- 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
package/lib/esm/Icon/Icon.js
CHANGED
|
@@ -14,6 +14,7 @@ const Icon = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
14
14
|
tokens,
|
|
15
15
|
scalesWithText = false,
|
|
16
16
|
style = {},
|
|
17
|
+
testID,
|
|
17
18
|
dataSet
|
|
18
19
|
} = _ref;
|
|
19
20
|
const themeTokens = useThemeTokens('Icon', tokens, variant);
|
|
@@ -37,6 +38,7 @@ const Icon = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
37
38
|
};
|
|
38
39
|
const getIconContentForMobile = () => {
|
|
39
40
|
return /*#__PURE__*/_jsx(View, {
|
|
41
|
+
testID: testID,
|
|
40
42
|
style: {
|
|
41
43
|
backgroundColor: themeTokens.backgroundColor,
|
|
42
44
|
borderRadius: themeTokens.borderRadius,
|
|
@@ -46,6 +48,7 @@ const Icon = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
46
48
|
});
|
|
47
49
|
};
|
|
48
50
|
return Platform.OS === 'web' ? /*#__PURE__*/_jsx(View, {
|
|
51
|
+
testID: testID,
|
|
49
52
|
ref: ref
|
|
50
53
|
// eslint-disable-next-line react-native/no-inline-styles
|
|
51
54
|
,
|
|
@@ -7,6 +7,7 @@ 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: {
|
|
@@ -53,19 +54,23 @@ const GroupControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
53
54
|
hover,
|
|
54
55
|
focus,
|
|
55
56
|
label,
|
|
56
|
-
id
|
|
57
|
+
id,
|
|
58
|
+
variant = {}
|
|
57
59
|
} = _ref;
|
|
58
60
|
const {
|
|
59
61
|
selectedId,
|
|
60
62
|
setSelectedId
|
|
61
63
|
} = useListboxContext();
|
|
62
|
-
const
|
|
64
|
+
const isSecondLevel = variant?.secondLevel === true;
|
|
65
|
+
const tokens = useThemeTokens('Listbox', variant, {}, {
|
|
63
66
|
expanded,
|
|
64
67
|
pressed,
|
|
65
68
|
hover,
|
|
66
69
|
current: selectedId === id && id !== undefined,
|
|
67
|
-
focus
|
|
70
|
+
focus,
|
|
71
|
+
secondLevel: isSecondLevel
|
|
68
72
|
});
|
|
73
|
+
const displayIcon = isSecondLevel ? tokens.secondLevelParentIcon : tokens.groupIcon;
|
|
69
74
|
return /*#__PURE__*/_jsxs(View, {
|
|
70
75
|
onPress: () => setSelectedId(id),
|
|
71
76
|
style: [styles.container, selectContainerStyles(tokens)],
|
|
@@ -76,8 +81,8 @@ const GroupControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
76
81
|
}), /*#__PURE__*/_jsx(Spacer, {
|
|
77
82
|
space: 1,
|
|
78
83
|
direction: "row"
|
|
79
|
-
}),
|
|
80
|
-
icon:
|
|
84
|
+
}), displayIcon && /*#__PURE__*/_jsx(Icon, {
|
|
85
|
+
icon: displayIcon,
|
|
81
86
|
tokens: {
|
|
82
87
|
color: tokens.groupColor
|
|
83
88
|
},
|
|
@@ -94,6 +99,7 @@ GroupControl.propTypes = {
|
|
|
94
99
|
pressed: PropTypes.bool,
|
|
95
100
|
hover: PropTypes.bool,
|
|
96
101
|
focus: PropTypes.bool,
|
|
97
|
-
label: PropTypes.string
|
|
102
|
+
label: PropTypes.string,
|
|
103
|
+
variant: variantProp.propType
|
|
98
104
|
};
|
|
99
105
|
export default GroupControl;
|
|
@@ -10,11 +10,14 @@ 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
|
});
|
|
20
23
|
const selectContainerStyles = tokens => ({
|
|
@@ -34,12 +37,15 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
34
37
|
LinkRouter,
|
|
35
38
|
itemRouterProps,
|
|
36
39
|
onClose,
|
|
40
|
+
copy = 'en',
|
|
41
|
+
dictionary = defaultDictionary,
|
|
37
42
|
variant,
|
|
38
43
|
tokens,
|
|
39
44
|
testID
|
|
40
45
|
} = _ref;
|
|
41
46
|
const initialOpen = getInitialOpen(items, defaultSelectedId);
|
|
42
47
|
const [selectedId, setSelectedId] = React.useState(defaultSelectedId);
|
|
48
|
+
const [activeSecondLevelGroup, setActiveSecondLevelGroup] = React.useState(null);
|
|
43
49
|
const listboxTokens = useThemeTokens('Listbox', tokens, variant);
|
|
44
50
|
|
|
45
51
|
// We need to keep track of each item's ref in order to be able to
|
|
@@ -89,11 +95,14 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
89
95
|
}
|
|
90
96
|
return () => {};
|
|
91
97
|
}, [onClose, handleKeydown]);
|
|
98
|
+
const contextValue = {
|
|
99
|
+
selectedId,
|
|
100
|
+
setSelectedId,
|
|
101
|
+
activeSecondLevelGroup,
|
|
102
|
+
setActiveSecondLevelGroup
|
|
103
|
+
};
|
|
92
104
|
return /*#__PURE__*/_jsx(ListboxContext.Provider, {
|
|
93
|
-
value:
|
|
94
|
-
selectedId,
|
|
95
|
-
setSelectedId
|
|
96
|
-
},
|
|
105
|
+
value: contextValue,
|
|
97
106
|
children: /*#__PURE__*/_jsx(ExpandCollapse, {
|
|
98
107
|
initialOpen: initialOpen,
|
|
99
108
|
maxOpen: 1,
|
|
@@ -115,6 +124,9 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
115
124
|
itemRefs.current[index] = currentItemRef;
|
|
116
125
|
return currentItemRef;
|
|
117
126
|
};
|
|
127
|
+
if (!nestedItems && activeSecondLevelGroup) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
118
130
|
return nestedItems ? /*#__PURE__*/_createElement(ListboxGroup, {
|
|
119
131
|
...item,
|
|
120
132
|
expandProps: expandProps,
|
|
@@ -123,7 +135,12 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
123
135
|
prevItemRef: itemRefs.current[index - 1] ?? null,
|
|
124
136
|
nextItemRef: itemRefs.current[index + 1] ?? null,
|
|
125
137
|
ref: index === 0 ? firstItemRef : itemRef,
|
|
126
|
-
key: itemId
|
|
138
|
+
key: itemId,
|
|
139
|
+
copy: copy,
|
|
140
|
+
dictionary: dictionary,
|
|
141
|
+
variant: variant,
|
|
142
|
+
tokens: tokens,
|
|
143
|
+
onClose: onClose
|
|
127
144
|
}) : /*#__PURE__*/_createElement(ListboxItem, {
|
|
128
145
|
...item,
|
|
129
146
|
key: itemId,
|
|
@@ -132,7 +149,9 @@ const Listbox = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
132
149
|
itemRouterProps: itemRouterProps,
|
|
133
150
|
prevItemRef: itemRefs.current[index - 1] ?? null,
|
|
134
151
|
nextItemRef: itemRefs.current[index + 1] ?? null,
|
|
135
|
-
ref: index === 0 ? firstItemRef : itemRef
|
|
152
|
+
ref: index === 0 ? firstItemRef : itemRef,
|
|
153
|
+
variant: variant,
|
|
154
|
+
tokens: tokens
|
|
136
155
|
});
|
|
137
156
|
})
|
|
138
157
|
})
|
|
@@ -168,6 +187,21 @@ Listbox.propTypes = {
|
|
|
168
187
|
* Test ID for testing
|
|
169
188
|
*/
|
|
170
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
|
+
}),
|
|
171
205
|
/**
|
|
172
206
|
* Listbox variant
|
|
173
207
|
*/
|
|
@@ -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,
|
|
@@ -81,7 +179,7 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
81
179
|
contentPanelBackgroundColor: 'transparent'
|
|
82
180
|
},
|
|
83
181
|
controlRef: ref,
|
|
84
|
-
children: /*#__PURE__*/_jsx(View, {
|
|
182
|
+
children: !isSecondLevel && /*#__PURE__*/_jsx(View, {
|
|
85
183
|
style: styles.list,
|
|
86
184
|
children: items.map((item, index) => {
|
|
87
185
|
return /*#__PURE__*/_jsx(ListboxItem, {
|
|
@@ -91,6 +189,8 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
91
189
|
isChild: true,
|
|
92
190
|
LinkRouter: LinkRouter,
|
|
93
191
|
linkRouterProps: linkRouterProps,
|
|
192
|
+
variant: variant,
|
|
193
|
+
tokens: tokens,
|
|
94
194
|
...(index === 0 && {
|
|
95
195
|
prevItemRef
|
|
96
196
|
}),
|
|
@@ -109,6 +209,10 @@ const ListboxGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
109
209
|
ListboxGroup.displayName = 'ListboxGroup';
|
|
110
210
|
ListboxGroup.propTypes = {
|
|
111
211
|
...withLinkRouter.propTypes,
|
|
212
|
+
/**
|
|
213
|
+
* Unique identifier for the group
|
|
214
|
+
*/
|
|
215
|
+
id: PropTypes.string,
|
|
112
216
|
label: PropTypes.string,
|
|
113
217
|
items: PropTypes.arrayOf(PropTypes.shape({
|
|
114
218
|
href: PropTypes.string,
|
|
@@ -121,6 +225,33 @@ ListboxGroup.propTypes = {
|
|
|
121
225
|
/**
|
|
122
226
|
* Use this callback to redirect the focus after it leaves the last item of the group.
|
|
123
227
|
*/
|
|
124
|
-
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
|
|
125
256
|
};
|
|
126
257
|
export default ListboxGroup;
|
|
@@ -31,9 +31,10 @@ const DropdownOverlay = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
31
31
|
minWidth,
|
|
32
32
|
onLayout,
|
|
33
33
|
tokens,
|
|
34
|
-
testID
|
|
34
|
+
testID,
|
|
35
|
+
variant
|
|
35
36
|
} = _ref;
|
|
36
|
-
const systemTokens = useThemeTokens('Listbox',
|
|
37
|
+
const systemTokens = useThemeTokens('Listbox', variant, tokens);
|
|
37
38
|
return /*#__PURE__*/_jsx(View, {
|
|
38
39
|
ref: ref,
|
|
39
40
|
onLayout: onLayout,
|
|
@@ -45,11 +46,14 @@ const DropdownOverlay = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
45
46
|
children: /*#__PURE__*/_jsx(Card, {
|
|
46
47
|
tokens: {
|
|
47
48
|
shadow: systemTokens.shadow,
|
|
49
|
+
borderRadius: systemTokens.borderRadius,
|
|
50
|
+
...(Platform.OS === 'web' && {
|
|
51
|
+
overflowY: 'hidden'
|
|
52
|
+
}),
|
|
48
53
|
paddingBottom: paddingVertical,
|
|
49
54
|
paddingTop: paddingVertical,
|
|
50
55
|
paddingLeft: paddingHorizontal,
|
|
51
|
-
paddingRight: paddingHorizontal
|
|
52
|
-
...tokens
|
|
56
|
+
paddingRight: paddingHorizontal
|
|
53
57
|
},
|
|
54
58
|
children: children
|
|
55
59
|
})
|
|
@@ -77,6 +81,7 @@ DropdownOverlay.propTypes = {
|
|
|
77
81
|
minWidth: PropTypes.number,
|
|
78
82
|
onLayout: PropTypes.func,
|
|
79
83
|
tokens: PropTypes.object,
|
|
80
|
-
testID: PropTypes.string
|
|
84
|
+
testID: PropTypes.string,
|
|
85
|
+
variant: PropTypes.object
|
|
81
86
|
};
|
|
82
87
|
export default Platform.OS === 'web' ? withPortal(DropdownOverlay) : DropdownOverlay;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import View from "react-native-web/dist/exports/View";
|
|
4
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
5
|
+
import Text from "react-native-web/dist/exports/Text";
|
|
6
|
+
import Pressable from "react-native-web/dist/exports/Pressable";
|
|
7
|
+
import { useThemeTokens } from '../ThemeProvider';
|
|
8
|
+
import { useCopy, variantProp, copyPropTypes } from '../utils';
|
|
9
|
+
import Icon from '../Icon';
|
|
10
|
+
import IconButton from '../IconButton';
|
|
11
|
+
import Divider from '../Divider';
|
|
12
|
+
import defaultDictionary from './dictionary';
|
|
13
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
const styles = StyleSheet.create({
|
|
15
|
+
headerContainer: {
|
|
16
|
+
width: '100%'
|
|
17
|
+
},
|
|
18
|
+
headerContent: {
|
|
19
|
+
flexDirection: 'row',
|
|
20
|
+
alignItems: 'center',
|
|
21
|
+
width: '100%'
|
|
22
|
+
},
|
|
23
|
+
leftSection: {
|
|
24
|
+
flexDirection: 'row',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
flex: 1
|
|
27
|
+
},
|
|
28
|
+
backIcon: {
|
|
29
|
+
marginRight: 8,
|
|
30
|
+
flexShrink: 0
|
|
31
|
+
},
|
|
32
|
+
labelText: {
|
|
33
|
+
flex: 1
|
|
34
|
+
},
|
|
35
|
+
closeButton: {
|
|
36
|
+
flexShrink: 0
|
|
37
|
+
},
|
|
38
|
+
dividerContainer: {
|
|
39
|
+
width: '100%'
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
const selectHeaderContainerStyles = _ref => {
|
|
43
|
+
let {
|
|
44
|
+
secondLevelHeaderBackgroundColor
|
|
45
|
+
} = _ref;
|
|
46
|
+
return {
|
|
47
|
+
backgroundColor: secondLevelHeaderBackgroundColor
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const selectHeaderContentStyles = _ref2 => {
|
|
51
|
+
let {
|
|
52
|
+
secondLevelHeaderPaddingTop,
|
|
53
|
+
secondLevelHeaderPaddingBottom,
|
|
54
|
+
secondLevelHeaderPaddingLeft,
|
|
55
|
+
secondLevelHeaderPaddingRight
|
|
56
|
+
} = _ref2;
|
|
57
|
+
return {
|
|
58
|
+
paddingTop: secondLevelHeaderPaddingTop,
|
|
59
|
+
paddingBottom: secondLevelHeaderPaddingBottom,
|
|
60
|
+
paddingLeft: secondLevelHeaderPaddingLeft,
|
|
61
|
+
paddingRight: secondLevelHeaderPaddingRight
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
const selectLabelTextStyles = _ref3 => {
|
|
65
|
+
let {
|
|
66
|
+
secondLevelBackLinkFontName,
|
|
67
|
+
secondLevelBackLinkFontWeight,
|
|
68
|
+
secondLevelBackLinkFontSize,
|
|
69
|
+
secondLevelBackLinkColor
|
|
70
|
+
} = _ref3;
|
|
71
|
+
return {
|
|
72
|
+
fontFamily: `${secondLevelBackLinkFontName}${secondLevelBackLinkFontWeight}normal`,
|
|
73
|
+
fontSize: secondLevelBackLinkFontSize,
|
|
74
|
+
color: secondLevelBackLinkColor
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* SecondLevelHeader component for Listbox secondLevel variant.
|
|
80
|
+
* Displays a header with back button icon, title text, and close button (IconButton),
|
|
81
|
+
* separated from content by a Divider.
|
|
82
|
+
*/
|
|
83
|
+
const SecondLevelHeader = /*#__PURE__*/React.forwardRef((_ref4, ref) => {
|
|
84
|
+
let {
|
|
85
|
+
label,
|
|
86
|
+
onBack,
|
|
87
|
+
onClose,
|
|
88
|
+
copy = 'en',
|
|
89
|
+
dictionary = defaultDictionary,
|
|
90
|
+
tokens: tokensProp = {},
|
|
91
|
+
variant = {}
|
|
92
|
+
} = _ref4;
|
|
93
|
+
const tokens = useThemeTokens('Listbox', variant, tokensProp);
|
|
94
|
+
const getCopy = useCopy({
|
|
95
|
+
dictionary,
|
|
96
|
+
copy
|
|
97
|
+
});
|
|
98
|
+
const {
|
|
99
|
+
secondLevelBackIcon,
|
|
100
|
+
secondLevelBackIconColor,
|
|
101
|
+
secondLevelCloseIcon,
|
|
102
|
+
secondLevelCloseIconSize,
|
|
103
|
+
secondLevelCloseButtonBorderWidth,
|
|
104
|
+
secondLevelCloseButtonPadding,
|
|
105
|
+
secondLevelDividerColor,
|
|
106
|
+
secondLevelDividerWidth
|
|
107
|
+
} = tokens;
|
|
108
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
109
|
+
style: [styles.headerContainer, selectHeaderContainerStyles(tokens)],
|
|
110
|
+
ref: ref,
|
|
111
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
112
|
+
style: [styles.headerContent, selectHeaderContentStyles(tokens)],
|
|
113
|
+
children: [/*#__PURE__*/_jsxs(Pressable, {
|
|
114
|
+
onPress: onBack,
|
|
115
|
+
style: styles.leftSection,
|
|
116
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
117
|
+
style: styles.backIcon,
|
|
118
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
119
|
+
icon: secondLevelBackIcon,
|
|
120
|
+
tokens: {
|
|
121
|
+
color: secondLevelBackIconColor
|
|
122
|
+
},
|
|
123
|
+
variant: {
|
|
124
|
+
size: 'micro'
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
128
|
+
numberOfLines: 1,
|
|
129
|
+
style: [styles.labelText, selectLabelTextStyles(tokens)],
|
|
130
|
+
children: label
|
|
131
|
+
})]
|
|
132
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
133
|
+
style: styles.closeButton,
|
|
134
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
135
|
+
icon: secondLevelCloseIcon,
|
|
136
|
+
onPress: onClose,
|
|
137
|
+
accessibilityLabel: getCopy('closeMenu'),
|
|
138
|
+
tokens: {
|
|
139
|
+
iconSize: secondLevelCloseIconSize,
|
|
140
|
+
borderWidth: secondLevelCloseButtonBorderWidth,
|
|
141
|
+
padding: secondLevelCloseButtonPadding
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
})]
|
|
145
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
146
|
+
style: styles.dividerContainer,
|
|
147
|
+
children: /*#__PURE__*/_jsx(Divider, {
|
|
148
|
+
tokens: {
|
|
149
|
+
color: secondLevelDividerColor,
|
|
150
|
+
width: secondLevelDividerWidth
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
})]
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
SecondLevelHeader.displayName = 'SecondLevelHeader';
|
|
157
|
+
SecondLevelHeader.propTypes = {
|
|
158
|
+
/**
|
|
159
|
+
* The label text to display (typically the parent item label)
|
|
160
|
+
*/
|
|
161
|
+
label: PropTypes.string.isRequired,
|
|
162
|
+
/**
|
|
163
|
+
* Callback when back button is clicked
|
|
164
|
+
*/
|
|
165
|
+
onBack: PropTypes.func.isRequired,
|
|
166
|
+
/**
|
|
167
|
+
* Callback when close button is clicked
|
|
168
|
+
*/
|
|
169
|
+
onClose: PropTypes.func.isRequired,
|
|
170
|
+
/**
|
|
171
|
+
* Select English or French copy
|
|
172
|
+
*/
|
|
173
|
+
copy: copyPropTypes,
|
|
174
|
+
/**
|
|
175
|
+
* Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
|
|
176
|
+
*/
|
|
177
|
+
dictionary: PropTypes.shape({
|
|
178
|
+
en: PropTypes.shape({
|
|
179
|
+
closeMenu: PropTypes.string.isRequired
|
|
180
|
+
}),
|
|
181
|
+
fr: PropTypes.shape({
|
|
182
|
+
closeMenu: PropTypes.string.isRequired
|
|
183
|
+
})
|
|
184
|
+
}),
|
|
185
|
+
/**
|
|
186
|
+
* Custom tokens to override theme tokens
|
|
187
|
+
*/
|
|
188
|
+
tokens: PropTypes.object,
|
|
189
|
+
/**
|
|
190
|
+
* Variant configuration
|
|
191
|
+
*/
|
|
192
|
+
variant: variantProp.propType
|
|
193
|
+
};
|
|
194
|
+
export default SecondLevelHeader;
|