react-native-ui-lib
Version:
<p align="center"> <img src="https://user-images.githubusercontent.com/1780255/105469025-56759000-5ca0-11eb-993d-3568c1fd54f4.png" height="250px" style="display:block"/> </p> <p align="center">UI Toolset & Components Library for React Native</p> <p a
110 lines (96 loc) • 3.05 kB
JavaScript
import _pt from "prop-types";
import React, { PureComponent } from 'react';
import View from "../view";
import asPanViewConsumer from "./asPanViewConsumer";
/**
* @description: panResponderView component created to making listening to swipe and drag events easier.
* @notes: Has to be used as a child of a PanningProvider that also has a PanListenerView.
* The PanListenerView is the one that sends the drag\swipe events.
* @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/PanResponderScreen.tsx
* @gif: https://github.com/wix/react-native-ui-lib/blob/master/demo/showcase/PanResponderView/PanResponderView.gif?raw=true
*/
class PanResponderView extends PureComponent {
static propTypes = {
/**
* Will be called with the current location ({left, top}) when the pan has ended
*/
onPanLocationChanged: _pt.func,
/**
* Ignore panning events while this is true
*/
ignorePanning: _pt.bool,
/**
* Allow the view to be animated (send animation via style; default is false)
*/
isAnimated: _pt.bool,
context: _pt.shape({
isPanning: _pt.bool.isRequired
}).isRequired
};
static displayName = 'PanResponderView';
static defaultProps = {
isAnimated: false
};
initialLeft = 0;
initialTop = 0;
ref = React.createRef();
componentDidMount() {
this.setNativeProps(this.initialLeft, this.initialTop);
}
componentDidUpdate(prevProps) {
const {
ignorePanning
} = this.props;
const {
isPanning,
dragDeltas
} = this.props.context;
const {
isPanning: prevIsPanning,
dragDeltas: prevDragDeltas
} = prevProps.context;
if (!ignorePanning && !isPanning && prevIsPanning) {
this.onPanEnd();
}
if (!ignorePanning && isPanning && (dragDeltas.x || dragDeltas.y) && (dragDeltas.x !== prevDragDeltas.x || dragDeltas.y !== prevDragDeltas.y)) {
this.onDrag(dragDeltas);
}
}
onPanEnd() {
const location = {
left: this.left,
top: this.top
};
this.initialLeft = this.left || this.initialLeft;
this.initialTop = this.top || this.initialTop;
this.props.onPanLocationChanged?.(location); //@ts-expect-error
this.props.context.onPanLocationChanged?.(location);
}
onDrag(deltas) {
const left = this.initialLeft + (deltas.x ? Math.round(deltas.x) : 0);
const top = this.initialTop + (deltas.y ? Math.round(deltas.y) : 0);
this.setNativeProps(left, top);
}
setNativeProps(left, top) {
if (this.ref.current) {
this.ref.current.setNativeProps({
style: {
left,
top
}
});
this.left = left;
this.top = top;
}
}
render() {
const {
isAnimated,
...others
} = this.props;
return <View animated={isAnimated} ref={this.ref} pointerEvents={'box-none'} {...others}>
{this.props.children}
</View>;
}
}
export default asPanViewConsumer(PanResponderView);