-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Copy pathindex.js
85 lines (77 loc) · 3.48 KB
/
index.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
import _ from 'underscore';
import React, {Component} from 'react';
import {Pressable} from 'react-native';
import * as pressableWithSecondaryInteractionPropTypes from './pressableWithSecondaryInteractionPropTypes';
import styles from '../../styles/styles';
import * as DeviceCapabilities from '../../libs/DeviceCapabilities';
/**
* This is a special Pressable that calls onSecondaryInteraction when LongPressed, or right-clicked.
*/
class PressableWithSecondaryInteraction extends Component {
constructor(props) {
super(props);
this.executeSecondaryInteractionOnContextMenu = this.executeSecondaryInteractionOnContextMenu.bind(this);
}
componentDidMount() {
if (this.props.forwardedRef && _.isFunction(this.props.forwardedRef)) {
this.props.forwardedRef(this.pressableRef);
}
this.pressableRef.addEventListener('contextmenu', this.executeSecondaryInteractionOnContextMenu);
}
componentWillUnmount() {
this.pressableRef.removeEventListener('contextmenu', this.executeSecondaryInteractionOnContextMenu);
}
/**
* @param {contextmenu} e - A right-click MouseEvent.
* https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event
*/
executeSecondaryInteractionOnContextMenu(e) {
e.stopPropagation();
if (this.props.preventDefaultContentMenu) {
e.preventDefault();
}
/**
* This component prevents the tapped element from capturing focus.
* We need to blur this element when clicked as it opens modal that implements focus-trapping.
* When the modal is closed it focuses back to the last active element.
* Therefore it shifts the element to bring it back to focus.
* https://github.com/Expensify/App/issues/14148
*/
if (this.props.withoutFocusOnSecondaryInteraction && this.pressableRef) {
this.pressableRef.blur();
}
this.props.onSecondaryInteraction(e);
}
render() {
const defaultPressableProps = _.omit(this.props, ['onSecondaryInteraction', 'children', 'onLongPress']);
// On Web, Text does not support LongPress events thus manage inline mode with styling instead of using Text.
return (
<Pressable
style={this.props.inline && styles.dInline}
onPressIn={this.props.onPressIn}
onLongPress={(e) => {
if (DeviceCapabilities.hasHoverSupport()) {
return;
}
if (this.props.withoutFocusOnSecondaryInteraction && this.pressableRef) {
this.pressableRef.blur();
}
this.props.onSecondaryInteraction(e);
}}
onPressOut={this.props.onPressOut}
onPress={this.props.onPress}
ref={el => this.pressableRef = el}
// eslint-disable-next-line react/jsx-props-no-spreading
{...defaultPressableProps}
>
{this.props.children}
</Pressable>
);
}
}
PressableWithSecondaryInteraction.propTypes = pressableWithSecondaryInteractionPropTypes.propTypes;
PressableWithSecondaryInteraction.defaultProps = pressableWithSecondaryInteractionPropTypes.defaultProps;
export default React.forwardRef((props, ref) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<PressableWithSecondaryInteraction {...props} forwardedRef={ref} />
));