You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

488 lines
15 KiB

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _reactTweenState = require('react-tween-state');
var _reactTweenState2 = _interopRequireDefault(_reactTweenState);
var _NativeButton = require('./NativeButton');
var _NativeButton2 = _interopRequireDefault(_NativeButton);
var _styles = require('./styles');
var _styles2 = _interopRequireDefault(_styles);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _createReactClass = require('create-react-class');
var _createReactClass2 = _interopRequireDefault(_createReactClass);
var _reactNative = require('react-native');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var SwipeoutBtn = (0, _createReactClass2.default)({
displayName: 'SwipeoutBtn',
propTypes: {
backgroundColor: _propTypes2.default.string,
color: _propTypes2.default.string,
component: _propTypes2.default.node,
onPress: _propTypes2.default.func,
text: _propTypes2.default.node,
type: _propTypes2.default.string,
underlayColor: _propTypes2.default.string
},
getDefaultProps: function getDefaultProps() {
return {
backgroundColor: null,
color: null,
component: null,
underlayColor: null,
height: 0,
onPress: null,
disabled: false,
text: 'Click me',
type: '',
width: 0
};
},
render: function render() {
var btn = this.props;
var styleSwipeoutBtn = [_styles2.default.swipeoutBtn];
// apply "type" styles (delete || primary || secondary)
if (btn.type === 'delete') styleSwipeoutBtn.push(_styles2.default.colorDelete);else if (btn.type === 'primary') styleSwipeoutBtn.push(_styles2.default.colorPrimary);else if (btn.type === 'secondary') styleSwipeoutBtn.push(_styles2.default.colorSecondary);
// apply background color
if (btn.backgroundColor) styleSwipeoutBtn.push([{ backgroundColor: btn.backgroundColor }]);
styleSwipeoutBtn.push([{
height: btn.height,
width: btn.width
}]);
var styleSwipeoutBtnComponent = [];
// set button dimensions
styleSwipeoutBtnComponent.push([{
height: btn.height,
width: btn.width
}]);
var styleSwipeoutBtnText = [_styles2.default.swipeoutBtnText];
// apply text color
if (btn.color) styleSwipeoutBtnText.push({ color: btn.color });
return _react2.default.createElement(
_NativeButton2.default,
{
onPress: this.props.onPress,
underlayColor: this.props.underlayColor,
disabled: this.props.disabled,
style: [_styles2.default.swipeoutBtnTouchable, styleSwipeoutBtn],
textStyle: styleSwipeoutBtnText },
btn.component ? _react2.default.createElement(
_reactNative.View,
{ style: styleSwipeoutBtnComponent },
btn.component
) : btn.text
);
}
});
var Swipeout = (0, _createReactClass2.default)({
displayName: 'Swipeout',
mixins: [_reactTweenState2.default.Mixin],
propTypes: {
autoClose: _propTypes2.default.bool,
backgroundColor: _propTypes2.default.string,
close: _propTypes2.default.bool,
left: _propTypes2.default.array,
onOpen: _propTypes2.default.func,
onClose: _propTypes2.default.func,
right: _propTypes2.default.array,
scroll: _propTypes2.default.func,
style: (_reactNative.ViewPropTypes || _reactNative.View.propTypes).style,
sensitivity: _propTypes2.default.number,
buttonWidth: _propTypes2.default.number,
disabled: _propTypes2.default.bool
},
getDefaultProps: function getDefaultProps() {
return {
disabled: false,
rowID: -1,
sectionID: -1,
sensitivity: 50
};
},
getInitialState: function getInitialState() {
return {
autoClose: this.props.autoClose || false,
btnWidth: 0,
btnsLeftWidth: 0,
btnsRightWidth: 0,
contentHeight: 0,
contentPos: 0,
contentWidth: 0,
openedRight: false,
swiping: false,
tweenDuration: 160,
timeStart: null
};
},
componentWillMount: function componentWillMount() {
var _this = this;
this._panResponder = _reactNative.PanResponder.create({
onStartShouldSetPanResponder: function onStartShouldSetPanResponder(event, gestureState) {
return true;
},
onStartShouldSetPanResponderCapture: function onStartShouldSetPanResponderCapture(event, gestureState) {
return _this.state.openedLeft || _this.state.openedRight;
},
onMoveShouldSetPanResponderCapture: function onMoveShouldSetPanResponderCapture(event, gestureState) {
return Math.abs(gestureState.dx) > _this.props.sensitivity && Math.abs(gestureState.dy) <= _this.props.sensitivity;
},
onPanResponderGrant: this._handlePanResponderGrant,
onPanResponderMove: this._handlePanResponderMove,
onPanResponderRelease: this._handlePanResponderEnd,
onPanResponderTerminate: this._handlePanResponderEnd,
onShouldBlockNativeResponder: function onShouldBlockNativeResponder(event, gestureState) {
return false;
},
onPanResponderTerminationRequest: function onPanResponderTerminationRequest() {
return false;
}
});
},
componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
if (nextProps.close) this._close();
if (nextProps.openRight) this._openRight();
if (nextProps.openLeft) this._openLeft();
},
_handlePanResponderGrant: function _handlePanResponderGrant(e, gestureState) {
var _this2 = this;
if (this.props.disabled) return;
if (!this.state.openedLeft && !this.state.openedRight) {
this._callOnOpen();
} else {
this._callOnClose();
}
this.refs.swipeoutContent.measure(function (ox, oy, width, height) {
var buttonWidth = _this2.props.buttonWidth || width / 5;
_this2.setState({
btnWidth: buttonWidth,
btnsLeftWidth: _this2.props.left ? buttonWidth * _this2.props.left.length : 0,
btnsRightWidth: _this2.props.right ? buttonWidth * _this2.props.right.length : 0,
swiping: true,
timeStart: new Date().getTime()
});
});
},
_handlePanResponderMove: function _handlePanResponderMove(e, gestureState) {
if (this.props.disabled) return;
var posX = gestureState.dx;
var posY = gestureState.dy;
var leftWidth = this.state.btnsLeftWidth;
var rightWidth = this.state.btnsRightWidth;
if (this.state.openedRight) var posX = gestureState.dx - rightWidth;else if (this.state.openedLeft) var posX = gestureState.dx + leftWidth;
// prevent scroll if moveX is true
var moveX = Math.abs(posX) > Math.abs(posY);
if (this.props.scroll) {
if (moveX) this.props.scroll(false);else this.props.scroll(true);
}
if (this.state.swiping) {
// move content to reveal swipeout
if (posX < 0 && this.props.right) {
this.setState({ contentPos: Math.min(posX, 0) });
} else if (posX > 0 && this.props.left) {
this.setState({ contentPos: Math.max(posX, 0) });
};
}
},
_handlePanResponderEnd: function _handlePanResponderEnd(e, gestureState) {
if (this.props.disabled) return;
var posX = gestureState.dx;
var contentPos = this.state.contentPos;
var contentWidth = this.state.contentWidth;
var btnsLeftWidth = this.state.btnsLeftWidth;
var btnsRightWidth = this.state.btnsRightWidth;
// minimum threshold to open swipeout
var openX = contentWidth * 0.33;
// should open swipeout
var openLeft = posX > openX || posX > btnsLeftWidth / 2;
var openRight = posX < -openX || posX < -btnsRightWidth / 2;
// account for open swipeouts
if (this.state.openedRight) var openRight = posX - openX < -openX;
if (this.state.openedLeft) var openLeft = posX + openX > openX;
// reveal swipeout on quick swipe
var timeDiff = new Date().getTime() - this.state.timeStart < 200;
if (timeDiff) {
var openRight = posX < -openX / 10 && !this.state.openedLeft;
var openLeft = posX > openX / 10 && !this.state.openedRight;
}
if (this.state.swiping) {
if (openRight && contentPos < 0 && posX < 0) {
this._open(-btnsRightWidth, 'right');
} else if (openLeft && contentPos > 0 && posX > 0) {
this._open(btnsLeftWidth, 'left');
} else {
this._close();
}
}
// Allow scroll
if (this.props.scroll) this.props.scroll(true);
},
_tweenContent: function _tweenContent(state, endValue) {
this.tweenState(state, {
easing: _reactTweenState2.default.easingTypes.easeInOutQuad,
duration: endValue === 0 ? this.state.tweenDuration * 1.5 : this.state.tweenDuration,
endValue: endValue
});
},
_rubberBandEasing: function _rubberBandEasing(value, limit) {
if (value < 0 && value < limit) return limit - Math.pow(limit - value, 0.85);else if (value > 0 && value > limit) return limit + Math.pow(value - limit, 0.85);
return value;
},
// close swipeout on button press
_autoClose: function _autoClose(btn) {
if (this.state.autoClose) this._close();
var onPress = btn.onPress;
if (onPress) onPress();
},
_open: function _open(contentPos, direction) {
var left = direction === 'left';
var _props = this.props,
sectionID = _props.sectionID,
rowID = _props.rowID,
onOpen = _props.onOpen;
onOpen && onOpen(sectionID, rowID, direction);
this._tweenContent('contentPos', contentPos);
this.setState({
contentPos: contentPos,
openedLeft: left,
openedRight: !left,
swiping: false
});
},
_close: function _close() {
var _props2 = this.props,
sectionID = _props2.sectionID,
rowID = _props2.rowID,
onClose = _props2.onClose;
if (onClose && (this.state.openedLeft || this.state.openedRight)) {
var direction = this.state.openedRight ? 'right' : 'left';
onClose(sectionID, rowID, direction);
}
this._tweenContent('contentPos', 0);
this._callOnClose();
this.setState({
openedRight: false,
openedLeft: false,
swiping: false
});
},
_callOnClose: function _callOnClose() {
if (this.props.onClose) this.props.onClose(this.props.sectionID, this.props.rowID);
},
_callOnOpen: function _callOnOpen() {
if (this.props.onOpen) this.props.onOpen(this.props.sectionID, this.props.rowID);
},
_openRight: function _openRight() {
var _this3 = this;
this.refs.swipeoutContent.measure(function (ox, oy, width, height) {
var btnWidth = _this3.props.buttonWidth || width / 5;
_this3.setState({
btnWidth: btnWidth,
btnsRightWidth: _this3.props.right ? btnWidth * _this3.props.right.length : 0
}, function () {
_this3._tweenContent('contentPos', -_this3.state.btnsRightWidth);
_this3._callOnOpen();
_this3.setState({
contentPos: -_this3.state.btnsRightWidth,
openedLeft: false,
openedRight: true,
swiping: false
});
});
});
},
_openLeft: function _openLeft() {
var _this4 = this;
this.refs.swipeoutContent.measure(function (ox, oy, width, height) {
var btnWidth = _this4.props.buttonWidth || width / 5;
_this4.setState({
btnWidth: btnWidth,
btnsLeftWidth: _this4.props.left ? btnWidth * _this4.props.left.length : 0
}, function () {
_this4._tweenContent('contentPos', _this4.state.btnsLeftWidth);
_this4._callOnOpen();
_this4.setState({
contentPos: _this4.state.btnsLeftWidth,
openedLeft: true,
openedRight: false,
swiping: false
});
});
});
},
render: function render() {
var contentWidth = this.state.contentWidth;
var posX = this.getTweeningValue('contentPos');
var styleSwipeout = [_styles2.default.swipeout, this.props.style];
if (this.props.backgroundColor) {
styleSwipeout.push([{ backgroundColor: this.props.backgroundColor }]);
}
var limit = -this.state.btnsRightWidth;
if (posX > 0) var limit = this.state.btnsLeftWidth;
var styleLeftPos = {
left: {
left: 0,
overflow: 'hidden',
width: Math.min(limit * (posX / limit), limit)
}
};
var styleRightPos = {
right: {
left: Math.abs(contentWidth + Math.max(limit, posX)),
right: 0
}
};
var styleContentPos = {
content: {
transform: [{ translateX: this._rubberBandEasing(posX, limit) }]
}
};
var styleContent = [_styles2.default.swipeoutContent];
styleContent.push(styleContentPos.content);
var styleRight = [_styles2.default.swipeoutBtns];
styleRight.push(styleRightPos.right);
var styleLeft = [_styles2.default.swipeoutBtns];
styleLeft.push(styleLeftPos.left);
var isRightVisible = posX < 0;
var isLeftVisible = posX > 0;
return _react2.default.createElement(
_reactNative.View,
{ style: styleSwipeout },
_react2.default.createElement(
_reactNative.View,
_extends({
ref: 'swipeoutContent',
style: styleContent,
onLayout: this._onLayout
}, this._panResponder.panHandlers),
this.props.children
),
this._renderButtons(this.props.right, isRightVisible, styleRight),
this._renderButtons(this.props.left, isLeftVisible, styleLeft)
);
},
_onLayout: function _onLayout(event) {
var _event$nativeEvent$la = event.nativeEvent.layout,
width = _event$nativeEvent$la.width,
height = _event$nativeEvent$la.height;
this.setState({
contentWidth: width,
contentHeight: height
});
},
_renderButtons: function _renderButtons(buttons, isVisible, style) {
if (buttons && isVisible) {
return _react2.default.createElement(
_reactNative.View,
{ style: style },
buttons.map(this._renderButton)
);
} else {
return _react2.default.createElement(_reactNative.View, null);
}
},
_renderButton: function _renderButton(btn, i) {
var _this5 = this;
return _react2.default.createElement(SwipeoutBtn, {
backgroundColor: btn.backgroundColor,
color: btn.color,
component: btn.component,
disabled: btn.disabled,
height: this.state.contentHeight,
key: i,
onPress: function onPress() {
return _this5._autoClose(btn);
},
text: btn.text,
type: btn.type,
underlayColor: btn.underlayColor,
width: this.state.btnWidth
});
}
});
Swipeout.NativeButton = _NativeButton2.default;
Swipeout.SwipeoutButton = SwipeoutBtn;
exports.default = Swipeout;