citong-react-web
Version:
A framework for building web apps with React
220 lines (191 loc) • 6.64 kB
JavaScript
/**
* Copyright (c) 2015-present, Alibaba Group Holding Limited.
* All rights reserved.
*
* Copyright (c) 2015, Facebook, Inc. All rights reserved.
*
* @providesModule ReactTouchableHighlight
*/
'use strict';
import React, { Component } from 'react';
import View from 'ReactView';
import TimerMixin from 'react-timer-mixin';
import TouchableWithoutFeedback from 'ReactTouchableWithoutFeedback';
import { Mixin as TouchableMixin } from 'ReactTouchable';
import { Mixin as NativeMethodsMixin } from 'NativeMethodsMixin';
import StyleSheet from 'ReactStyleSheet';
import mixin from 'react-mixin';
import autobind from 'autobind-decorator';
type Event = Object;
var DEFAULT_PROPS = {
activeOpacity: 0.8,
underlayColor: 'black',
style: StyleSheet.create({
cursor: 'pointer'
})
};
var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
var CHILD_REF = 'childRef';
var UNDERLAY_REF = 'underlayRef';
var INACTIVE_CHILD_PROPS = {
style: StyleSheet.create({x: {opacity: 1.0}}).x,
};
var INACTIVE_UNDERLAY_PROPS = {
style: StyleSheet.create({x: {backgroundColor: 'transparent'}}).x,
};
class TouchableHighlight extends Component {
static propTypes = {
...TouchableWithoutFeedback.propTypes,
/**
* Determines what the opacity of the wrapped view should be when touch is
* active.
*/
activeOpacity: React.PropTypes.number,
/**
* The color of the underlay that will show through when the touch is
* active.
*/
underlayColor: React.PropTypes.string,
/**
* Called immediately after the underlay is shown
*/
onShowUnderlay: React.PropTypes.func,
/**
* Called immediately after the underlay is hidden
*/
onHideUnderlay: React.PropTypes.func,
}
static defaultProps = DEFAULT_PROPS
state = {...this.touchableGetInitialState(), ...this.computeSyntheticState(this.props)}
// Performance optimization to avoid constantly re-generating these objects.
computeSyntheticState(props) {
return {
activeProps: {
style: {
opacity: props.activeOpacity,
}
},
activeUnderlayProps: {
style: {
backgroundColor: props.underlayColor,
}
},
underlayStyle: [
DEFAULT_PROPS.style,
INACTIVE_UNDERLAY_PROPS.style,
props.style,
]
};
}
// componentDidMount() {
// // ensurePositiveDelayProps(this.props);
// // ensureComponentIsNative(this.refs[CHILD_REF]);
// },
componentDidUpdate() {
// ensureComponentIsNative(this.refs[CHILD_REF]);
}
componentWillReceiveProps(nextProps) {
// ensurePositiveDelayProps(nextProps);
if (nextProps.activeOpacity !== this.props.activeOpacity ||
nextProps.underlayColor !== this.props.underlayColor ||
nextProps.style !== this.props.style) {
this.setState(this.computeSyntheticState(nextProps));
}
}
/**
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
* defined on your component.
*/
touchableHandleActivePressIn(e: Event) {
this.clearTimeout(this._hideTimeout);
this._hideTimeout = null;
this._showUnderlay();
this.props.onPressIn && this.props.onPressIn(e);
}
touchableHandleActivePressOut(e: Event) {
if (!this._hideTimeout) {
this._hideUnderlay();
}
this.props.onPressOut && this.props.onPressOut(e);
}
touchableHandlePress(e: Event) {
this.clearTimeout(this._hideTimeout);
this._showUnderlay();
this._hideTimeout = this.setTimeout(this._hideUnderlay,
this.props.delayPressOut || 100);
var touchBank = e.touchHistory.touchBank[e.touchHistory.indexOfSingleActiveTouch];
if (touchBank) {
var offset = Math.sqrt(Math.pow(touchBank.startPageX - touchBank.currentPageX, 2)
+ Math.pow(touchBank.startPageY - touchBank.currentPageY, 2));
var velocity = (offset / (touchBank.currentTimeStamp - touchBank.startTimeStamp)) * 1000;
if (velocity < 100) this.props.onPress && this.props.onPress(e);
} else {
this.props.onPress && this.props.onPress(e);
}
}
touchableHandleLongPress(e: Event) {
this.props.onLongPress && this.props.onLongPress(e);
}
touchableGetPressRectOffset() {
return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant!
}
touchableGetHighlightDelayMS() {
return this.props.delayPressIn;
}
touchableGetLongPressDelayMS() {
return this.props.delayLongPress;
}
touchableGetPressOutDelayMS() {
return this.props.delayPressOut;
}
_showUnderlay() {
// if (!this.isMounted()) {
// return;
// }
this.refs[UNDERLAY_REF].setNativeProps(this.state.activeUnderlayProps);
this.refs[CHILD_REF].setNativeProps(this.state.activeProps);
this.props.onShowUnderlay && this.props.onShowUnderlay();
}
_hideUnderlay() {
this.clearTimeout(this._hideTimeout);
this._hideTimeout = null;
if (this.refs[UNDERLAY_REF]) {
this.refs[CHILD_REF].setNativeProps(INACTIVE_CHILD_PROPS);
this.refs[UNDERLAY_REF].setNativeProps({
...INACTIVE_UNDERLAY_PROPS,
style: this.state.underlayStyle,
});
this.props.onHideUnderlay && this.props.onHideUnderlay();
}
}
render() {
return (
<View
accessible={true}
accessibilityComponentType={this.props.accessibilityComponentType}
accessibilityTraits={this.props.accessibilityTraits}
ref={UNDERLAY_REF}
style={this.state.underlayStyle}
onLayout={this.props.onLayout}
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
onResponderTerminationRequest={this.touchableHandleResponderTerminationRequest}
onResponderGrant={this.touchableHandleResponderGrant}
onResponderMove={this.touchableHandleResponderMove}
onResponderRelease={this.touchableHandleResponderRelease}
onResponderTerminate={this.touchableHandleResponderTerminate}
testID={this.props.testID}>
{React.cloneElement(
React.Children.only(this.props.children),
{
ref: CHILD_REF,
}
)}
</View>
);
}
};
mixin.onClass(TouchableHighlight, TimerMixin);
mixin.onClass(TouchableHighlight, TouchableMixin);
mixin.onClass(TouchableHighlight, NativeMethodsMixin);
autobind(TouchableHighlight);
module.exports = TouchableHighlight;