Skip to content

Instantly share code, notes, and snippets.

@tuanmai
Created October 18, 2017 07:25
Show Gist options
  • Save tuanmai/22db90a2bebf1fcabb2b4fa8746c740d to your computer and use it in GitHub Desktop.
Save tuanmai/22db90a2bebf1fcabb2b4fa8746c740d to your computer and use it in GitHub Desktop.
import React, { PureComponent } from 'react';
import { View, Animated, Dimensions, Platform } from 'react-native';
import Interactable from 'react-native-interactable';
import { compose, mapProps } from 'recompose';
const { width } = Dimensions.get('window');
/* eslint-disable */
/*
* Origin state
+ +
| |
| |
+---+---+--+--+--+--------------------------------------------------+
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
+---+---+--+--+--+--------------------------------------------------+
| |
| |
<--------------------> Viewport |
width + +
* Left state
* move width
+ +
| |
| |
+---+---+--+--+--+---+----------------------------------------------+
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
+---+---+--+--+--+---+----------------------------------------------+
| |
| |
| Viewport |
+ +
* Right state
* move -width
+ +
| |
| |
+---+---+--+--+--+---+---+-----------------+------------------------+
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
+---+---+--+--+--+---+---+-----------------+------------------------+
| |
| |
| Viewport |
+ +
*/
class SwipableCell extends PureComponent {
static get defaultThresholdRate() {
return 0.3;
}
constructor(props) {
super(props);
this.swipeAni = new Animated.Value(0);
}
render() {
const {
LeftComponent,
RightComponent,
hasLeftComponent,
hasRightComponent,
snapPoints,
snapPointsCount,
boundaries,
onSwipeStart = () => {},
onSwipeEnd = () => {},
children,
} = this.props;
const onDragProps = () => {
if (Platform.OS === 'ios') {
return {
onDrag: event => {
const { state, x } = event.nativeEvent;
const threshold = SwipableCell.defaultThresholdRate * width;
if (state === 'end') {
let snapIndex = hasLeftComponent ? 1 : 0;
if (x > threshold) {
snapIndex -= 1;
}
if (x < 0) {
if (-x > threshold) {
snapIndex += 1;
}
}
this.refs.swipeComponent.snapTo({ index: snapIndex });
}
},
};
}
return {};
};
return (
<View>
<Interactable.View
ref="swipeComponent"
{...onDragProps()}
style={{
width: width * snapPointsCount,
top: 0,
left: hasLeftComponent ? -width : 0,
flexDirection: 'row',
}}
onSnap={({ nativeEvent: { id } }) => {
const { onSwipeLeftEnd, onSwipeRightEnd } = this.props;
if (id === 'left') {
onSwipeLeftEnd && onSwipeLeftEnd();
}
if (id === 'right') {
onSwipeRightEnd && onSwipeRightEnd();
}
}}
animatedValueX={this.swipeAni}
snapPoints={snapPoints}
horizontalOnly
boundaries={boundaries}
>
{
LeftComponent ?
<View
style={{
width,
}}
>
<LeftComponent
percentage={this.swipeAni.interpolate({
inputRange: [-width, 0, width],
outputRange: [0, 0, 1],
})}
{...this.props}
/>
</View>
: <View />
}
{children}
{
RightComponent ?
<View
style={{
width,
}}
>
<RightComponent
percentage={this.swipeAni.interpolate({
inputRange: [-width, 0, width],
outputRange: [1, 0, 0],
})}
{...this.props}
/>
</View>
: <View />
}
</Interactable.View>
</View>
);
}
}
export default compose(
mapProps(({
leftComponent: LeftComponent,
rightComponent: RightComponent,
...rest,
}) => {
// eslint-disable-next-line
let snapPoints = [{
x: 0,
id: 'middle',
}];
const hasLeftComponent = !!LeftComponent;
const hasRightComponent = !!RightComponent;
if (hasLeftComponent) {
snapPoints = [
{
x: width,
id: 'left',
},
...snapPoints,
]
}
if (hasRightComponent) {
snapPoints = [
...snapPoints,
{
x: -width,
id: 'right',
},
]
}
const boundaries = { left: hasRightComponent ? -width : 0, right: hasLeftComponent ? width : 0, bounce: 0.2 }
const snapPointsCount = snapPoints.length;
return {
LeftComponent,
RightComponent,
snapPoints,
boundaries,
snapPointsCount,
hasLeftComponent,
hasRightComponent,
...rest
}
}),
)(SwipableCell);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment