PointerEventsContainer.js
2.52 KB
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
import * as React from 'react';
import invariant from '../../utils/invariant';
import AnimatedValueSubscription from '../AnimatedValueSubscription';
const MIN_POSITION_OFFSET = 0.01;
/**
* Create a higher-order component that automatically computes the
* `pointerEvents` property for a component whenever navigation position
* changes.
*/
export default function create(Component) {
class Container extends React.Component {
constructor(props, context) {
super(props, context);
this._pointerEvents = this._computePointerEvents();
}
componentWillMount() {
this._onPositionChange = this._onPositionChange.bind(this);
this._onComponentRef = this._onComponentRef.bind(this);
}
componentDidMount() {
this._bindPosition(this.props);
}
componentWillUnmount() {
this._positionListener && this._positionListener.remove();
}
componentWillReceiveProps(nextProps) {
this._bindPosition(nextProps);
}
render() {
this._pointerEvents = this._computePointerEvents();
return <Component {...this.props} pointerEvents={this._pointerEvents} onComponentRef={this._onComponentRef} />;
}
_onComponentRef(component) {
this._component = component;
if (component) {
invariant(typeof component.setNativeProps === 'function', 'component must implement method `setNativeProps`');
}
}
_bindPosition(props) {
this._positionListener && this._positionListener.remove();
this._positionListener = new AnimatedValueSubscription(props.position, this._onPositionChange);
}
_onPositionChange() {
if (this._component) {
const pointerEvents = this._computePointerEvents();
if (this._pointerEvents !== pointerEvents) {
this._pointerEvents = pointerEvents;
this._component.setNativeProps({ pointerEvents });
}
}
}
_computePointerEvents() {
const { navigation, position, scene } = this.props;
if (scene.isStale || navigation.state.index !== scene.index) {
// The scene isn't focused.
return scene.index > navigation.state.index ? 'box-only' : 'none';
}
const offset = position.__getAnimatedValue() - navigation.state.index;
if (Math.abs(offset) > MIN_POSITION_OFFSET) {
// The positon is still away from scene's index.
// Scene's children should not receive touches until the position
// is close enough to scene's index.
return 'box-only';
}
return 'auto';
}
}
return Container;
}