-
-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy pathOverflowMenu.js
97 lines (90 loc) · 2.75 KB
/
OverflowMenu.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// @flow
import * as React from 'react';
import {
extractOverflowButtonData,
overflowMenuPressHandlerDropdownMenu,
defaultOnOverflowMenuPress,
type OnOverflowMenuPressParams,
} from '../overflowMenuPressHandlers';
import { OVERFLOW_TOP, OverflowMenuContext } from './OverflowMenuContext';
import { View, StyleSheet, Platform } from 'react-native';
import { HeaderButton } from '../HeaderButton';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
import { OVERFLOW_BUTTON_TEST_ID } from '../e2e';
import { ButtonsWrapper } from '../ButtonsWrapper';
export type OverflowMenuProps = {|
children: React.Node,
OverflowIcon: React.Element<any>,
style?: ViewStyleProp,
testID: string,
accessibilityLabel: string,
onPress: (OnOverflowMenuPressParams) => any,
left: boolean,
|};
export const OverflowMenu = ({
children,
OverflowIcon,
accessibilityLabel,
testID,
style,
onPress,
left,
}: OverflowMenuProps) => {
const toggleMenu = React.useContext(OverflowMenuContext);
const btnRef = React.useRef<View | null>(null);
const renderButtonElement = React.useCallback(() => OverflowIcon, [OverflowIcon]);
const usedOnPress = React.useCallback(() => {
const titlesAndOnPresses =
onPress === overflowMenuPressHandlerDropdownMenu ? [] : extractOverflowButtonData(children);
onPress({
children,
hiddenButtons: titlesAndOnPresses,
overflowButtonRef: btnRef.current,
_private_toggleMenu: toggleMenu,
});
}, [children, onPress, toggleMenu]);
const validChildren = React.Children.toArray(children).filter(React.isValidElement);
if (validChildren.length === 0) {
return null;
}
return (
<ButtonsWrapper left={left}>
<View ref={btnRef} collapsable={false} style={styles.overflowMenuView} />
<HeaderButton
title="overflow menu"
renderButtonElement={renderButtonElement}
style={[styles.icon, style]}
onPress={usedOnPress}
accessibilityLabel={accessibilityLabel}
testID={testID}
/>
</ButtonsWrapper>
);
};
OverflowMenu.defaultProps = {
accessibilityLabel: 'More options',
OverflowIcon: <View />,
onPress: defaultOnOverflowMenuPress,
testID: OVERFLOW_BUTTON_TEST_ID,
left: false, // this is needed only when OverflowMenu is rendered without HeaderButtons
};
const styles = StyleSheet.create({
icon: {
...Platform.select({
android: {
marginRight: 9,
marginLeft: 7,
},
}),
},
overflowMenuView: {
// these are really just needed bcs of the native android popup menu
position: 'absolute',
top: -OVERFLOW_TOP,
// TODO android actually has a little gap on the right of the menu
right: 0,
backgroundColor: 'transparent',
width: 1,
height: 1,
},
});