feat: add third party gestures integration (#143)

* chore: added simultaneousHandlers and waitFor props

* chore: added view pager example
This commit is contained in:
Mo Gorhom
2021-01-03 20:08:07 +01:00
committed by GitHub
parent ac1c8ff096
commit aa329d7216
11 changed files with 274 additions and 13 deletions

View File

@@ -6,13 +6,15 @@
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start"
"start": "react-native start",
"posxtinstall": "npx patch-package"
},
"dependencies": {
"@gorhom/portal": "^0.1.4",
"@gorhom/showcase-template": "^1.0.2",
"@react-native-community/blur": "^3.6.0",
"@react-native-community/masked-view": "0.1.10",
"@react-navigation/material-top-tabs": "^5.3.10",
"@react-navigation/native": "^5.8.10",
"@react-navigation/stack": "^5.12.8",
"faker": "^4.1.0",
@@ -25,7 +27,8 @@
"react-native-reanimated": "^2.0.0-rc.1",
"react-native-redash": "^16.0.4",
"react-native-safe-area-context": "0.7.3",
"react-native-screens": "^2.16.1"
"react-native-screens": "^2.16.1",
"react-native-tab-view": "^2.15.2"
},
"devDependencies": {
"@babel/core": "^7.12.10",

View File

@@ -0,0 +1,138 @@
diff --git a/node_modules/react-native-tab-view/lib/commonjs/Pager.js b/node_modules/react-native-tab-view/lib/commonjs/Pager.js
index 1c491e8..14241b1 100644
--- a/node_modules/react-native-tab-view/lib/commonjs/Pager.js
+++ b/node_modules/react-native-tab-view/lib/commonjs/Pager.js
@@ -96,7 +96,10 @@ class Pager extends React.Component {
_defineProperty(this, "mounted", false);
+ _defineProperty(this, "gestureHandlerRef", /*#__PURE__*/React.createRef());
+
_defineProperty(this, "providerVal", {
+ pagerRef: this.gestureHandlerRef,
addGestureHandlerRef: ref => {
if (!this.state.childPanGestureHandlerRefs.includes(ref) && this.mounted) {
this.setState(prevState => ({
@@ -106,8 +109,6 @@ class Pager extends React.Component {
}
});
- _defineProperty(this, "gestureHandlerRef", /*#__PURE__*/React.createRef());
-
_defineProperty(this, "clock", new Clock());
_defineProperty(this, "velocityX", new Value(0));
diff --git a/node_modules/react-native-tab-view/lib/commonjs/index.js b/node_modules/react-native-tab-view/lib/commonjs/index.js
index e3f00fc..9a39fc8 100644
--- a/node_modules/react-native-tab-view/lib/commonjs/index.js
+++ b/node_modules/react-native-tab-view/lib/commonjs/index.js
@@ -15,6 +15,12 @@ Object.defineProperty(exports, "TabView", {
return _TabView.default;
}
});
+Object.defineProperty(exports, "Pager", {
+ enumerable: true,
+ get: function get() {
+ return _Pager.default;
+ }
+});
Object.defineProperty(exports, "TabBarIndicator", {
enumerable: true,
get: function get() {
@@ -60,5 +66,7 @@ var _SceneMap = _interopRequireDefault(require("./SceneMap"));
var _ScrollPager = _interopRequireDefault(require("./ScrollPager"));
+var _Pager = _interopRequireDefault(require("./Pager"));
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/react-native-tab-view/lib/module/Pager.js b/node_modules/react-native-tab-view/lib/module/Pager.js
index 406e30a..4482bcb 100644
--- a/node_modules/react-native-tab-view/lib/module/Pager.js
+++ b/node_modules/react-native-tab-view/lib/module/Pager.js
@@ -78,7 +78,10 @@ export default class Pager extends React.Component {
_defineProperty(this, "mounted", false);
+ _defineProperty(this, "gestureHandlerRef", /*#__PURE__*/React.createRef());
+
_defineProperty(this, "providerVal", {
+ pagerRef: this.gestureHandlerRef,
addGestureHandlerRef: ref => {
if (!this.state.childPanGestureHandlerRefs.includes(ref) && this.mounted) {
this.setState(prevState => ({
@@ -88,8 +91,6 @@ export default class Pager extends React.Component {
}
});
- _defineProperty(this, "gestureHandlerRef", /*#__PURE__*/React.createRef());
-
_defineProperty(this, "clock", new Clock());
_defineProperty(this, "velocityX", new Value(0));
diff --git a/node_modules/react-native-tab-view/lib/module/index.js b/node_modules/react-native-tab-view/lib/module/index.js
index c687a54..5466d89 100644
--- a/node_modules/react-native-tab-view/lib/module/index.js
+++ b/node_modules/react-native-tab-view/lib/module/index.js
@@ -5,4 +5,5 @@ export { default as TabBarItem } from './TabBarItem';
export { default as TouchableItem } from './TouchableItem';
export { default as SceneMap } from './SceneMap';
export { default as ScrollPager } from './ScrollPager';
+export { default as Pager } from './Pager';
//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/react-native-tab-view/lib/typescript/src/index.d.ts b/node_modules/react-native-tab-view/lib/typescript/src/index.d.ts
index 60cada6..2dc8881 100644
--- a/node_modules/react-native-tab-view/lib/typescript/src/index.d.ts
+++ b/node_modules/react-native-tab-view/lib/typescript/src/index.d.ts
@@ -9,4 +9,5 @@ export type { Props as TabBarItemProps } from './TabBarItem';
export { default as TouchableItem } from './TouchableItem';
export { default as SceneMap } from './SceneMap';
export { default as ScrollPager } from './ScrollPager';
+export { default as Pager } from './Pager';
export type { Route, NavigationState, SceneRendererProps } from './types';
diff --git a/node_modules/react-native-tab-view/src/Pager.tsx b/node_modules/react-native-tab-view/src/Pager.tsx
index 3441d69..1202c35 100644
--- a/node_modules/react-native-tab-view/src/Pager.tsx
+++ b/node_modules/react-native-tab-view/src/Pager.tsx
@@ -245,9 +245,15 @@ export default class Pager<T extends Route> extends React.Component<
static contextType = PagerContext;
+ // PanGestureHandler ref used for coordination with parent handlers
+ private gestureHandlerRef: React.RefObject<
+ PanGestureHandler
+ > = React.createRef();
+
// Mechanism to add child PanGestureHandler refs in the case that this
// Pager is a parent to child Pagers. Allows for coordination between handlers
private providerVal = {
+ pagerRef: this.gestureHandlerRef,
addGestureHandlerRef: (ref: React.RefObject<PanGestureHandler>) => {
if (
!this.state.childPanGestureHandlerRefs.includes(ref) &&
@@ -263,11 +269,6 @@ export default class Pager<T extends Route> extends React.Component<
},
};
- // PanGestureHandler ref used for coordination with parent handlers
- private gestureHandlerRef: React.RefObject<
- PanGestureHandler
- > = React.createRef();
-
// Clock used for tab transition animations
private clock = new Clock();
diff --git a/node_modules/react-native-tab-view/src/index.tsx b/node_modules/react-native-tab-view/src/index.tsx
index ce01571..a7dffb4 100644
--- a/node_modules/react-native-tab-view/src/index.tsx
+++ b/node_modules/react-native-tab-view/src/index.tsx
@@ -14,5 +14,6 @@ export { default as TouchableItem } from './TouchableItem';
export { default as SceneMap } from './SceneMap';
export { default as ScrollPager } from './ScrollPager';
+export { default as Pager } from './Pager';
export type { Route, NavigationState, SceneRendererProps } from './types';

View File

@@ -133,6 +133,16 @@ function App() {
require('./screens/advanced/DynamicSnapPointExample').default
}
/>
<Stack.Screen
name="Advanced/ViewPagerExample"
options={{
title: 'ViewPager Example',
}}
getComponent={() =>
require('./screens/advanced/ViewPagerExample').default
}
/>
</Stack.Navigator>
</NavigationContainer>
</AppearanceProvider>

View File

@@ -70,6 +70,10 @@ const data = [
name: 'Dynamic Snap Point',
slug: 'Advanced/DynamicSnapPointExample',
},
{
name: 'View Pager',
slug: 'Advanced/ViewPagerExample',
},
],
},
];

View File

@@ -0,0 +1,61 @@
import React, { useContext, useMemo } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import { Pager } from 'react-native-tab-view';
import BottomSheet from '@gorhom/bottom-sheet';
import ContactList from '../../components/contactList';
const FirstRoute = () => {
// @ts-ignore
const { pagerRef } = useContext(Pager.contextType);
const snapPoints = useMemo(() => ['25%', '50%', '90%'], []);
return (
<View style={[styles.scene, styles.firstScene]}>
<BottomSheet
snapPoints={snapPoints}
waitFor={pagerRef}
animateOnMount={true}
>
<ContactList type="FlatList" count={15} />
</BottomSheet>
</View>
);
};
const SecondRoute = () => (
<View style={[styles.scene, styles.secondScene]}>
<Text style={styles.emoji}>🙈</Text>
</View>
);
const Tab = createMaterialTopTabNavigator();
const ViewPagerScreen = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={FirstRoute} />
<Tab.Screen name="Settings" component={SecondRoute} />
</Tab.Navigator>
);
};
const styles = StyleSheet.create({
scene: {
flex: 1,
},
firstScene: {
backgroundColor: '#ff4081',
},
secondScene: {
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#673ab7',
},
emoji: {
fontSize: 46,
},
});
export default ViewPagerScreen;

View File

@@ -19,6 +19,7 @@ export type AppStackParamsList = {
['Advanced/BackdropExample']: undefined;
['Advanced/MapExample']: undefined;
['Advanced/DynamicSnapPointExample']: undefined;
['Advanced/ViewPagerExample']: undefined;
};
export type Contact = {

View File

@@ -1102,6 +1102,13 @@
query-string "^6.13.6"
react-is "^16.13.0"
"@react-navigation/material-top-tabs@^5.3.10":
version "5.3.10"
resolved "https://registry.yarnpkg.com/@react-navigation/material-top-tabs/-/material-top-tabs-5.3.10.tgz#158b694e87bff2eb9577e8142415de8ac3547412"
integrity sha512-mmQYEBhcLp1DwvuD8+HiFtYPk5zP43272C/38iX2T8AblcwRdoJejuO/GUzQcEPrmZHjeAnA5GDaMiXQM4EXLQ==
dependencies:
color "^3.1.3"
"@react-navigation/native@^5.8.10":
version "5.8.10"
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-5.8.10.tgz#3fe806abff9efb085bcf595212803dd05a1347ca"
@@ -3904,6 +3911,11 @@ react-native-screens@^2.16.1:
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-2.16.1.tgz#b105a127378d90018a46daf0c2f6518fca60c06f"
integrity sha512-WZ7m0sBDVaHbBnlHxwQnUlI6KNfQKHq+Unfw+VBuAlnSXvT+aw6Bb/K2bUlHzBgvrPjwY3Spc7ZERFuTwRLLwg==
react-native-tab-view@^2.15.2:
version "2.15.2"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz#4bc7832d33a119306614efee667509672a7ee64e"
integrity sha512-2hxLkBnZtEKFDyfvNO5EUywhy3f/EiLOBO8SWqKj4BMBTO0QwnybaPE5MVF00Fhz+VA4+h/iI40Dkrrtq70dGg==
react-native@0.63.4:
version "0.63.4"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.63.4.tgz#2210fdd404c94a5fa6b423c6de86f8e48810ec36"

View File

@@ -92,6 +92,11 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
// animated callback shared values
animatedPosition: _providedAnimatedPosition,
animatedIndex: _providedAnimatedIndex,
// gestures
simultaneousHandlers: _providedSimultaneousHandlers,
waitFor: _providedWaitFor,
// callbacks
onChange: _providedOnChange,
onAnimate: _providedOnAnimate,
@@ -395,6 +400,8 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
contentPanGestureHandler,
scrollableContentOffsetY,
scrollableDecelerationRate,
simultaneousHandlers: _providedSimultaneousHandlers,
waitFor: _providedWaitFor,
setScrollableRef: handleSettingScrollableRef,
removeScrollableRef,
}),
@@ -409,6 +416,8 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
scrollableContentOffsetY,
scrollableDecelerationRate,
enableContentPanningGesture,
_providedSimultaneousHandlers,
_providedWaitFor,
]
);
const externalContextVariables = useMemo(

View File

@@ -1,10 +1,13 @@
import type React from 'react';
import type Animated from 'react-native-reanimated';
import type { GestureHandlerProperties } from 'react-native-gesture-handler';
import type { BottomSheetHandleProps } from '../bottomSheetHandle';
import type { BottomSheetBackdropProps } from '../bottomSheetBackdrop';
import type { BottomSheetBackgroundProps } from '../bottomSheetBackground';
export interface BottomSheetProps extends BottomSheetAnimationConfigs {
export interface BottomSheetProps
extends BottomSheetAnimationConfigs,
Pick<GestureHandlerProperties, 'waitFor' | 'simultaneousHandlers'> {
// configuration
/**
* Initial snap index, you also could provide `-1` to initiate bottom sheet in closed state.

View File

@@ -20,16 +20,32 @@ const BottomSheetDraggableViewComponent = ({
enableContentPanningGesture,
contentWrapperGestureRef,
contentPanGestureHandler,
simultaneousHandlers: _providedSimultaneousHandlers,
waitFor,
} = useBottomSheetInternal();
// variables
const simultaneousHandlers = useMemo(
() =>
nativeGestureRef
? [contentWrapperGestureRef, nativeGestureRef]
: contentWrapperGestureRef,
[contentWrapperGestureRef, nativeGestureRef]
);
const simultaneousHandlers = useMemo(() => {
const refs = [contentWrapperGestureRef];
if (nativeGestureRef) {
refs.push(nativeGestureRef);
}
if (_providedSimultaneousHandlers) {
if (Array.isArray(_providedSimultaneousHandlers)) {
refs.push(..._providedSimultaneousHandlers);
} else {
refs.push(_providedSimultaneousHandlers);
}
}
return refs;
}, [
_providedSimultaneousHandlers,
contentWrapperGestureRef,
nativeGestureRef,
]);
// styles
const containerStyle = useMemo(
@@ -43,6 +59,7 @@ const BottomSheetDraggableViewComponent = ({
enabled={enableContentPanningGesture}
simultaneousHandlers={simultaneousHandlers}
shouldCancelWhenOutside={false}
waitFor={waitFor}
onGestureEvent={contentPanGestureHandler}
>
<Animated.View style={containerStyle} {...rest}>

View File

@@ -1,7 +1,10 @@
import { createContext, Ref, RefObject } from 'react';
import type { TapGestureHandler } from 'react-native-gesture-handler';
import type {
TapGestureHandler,
GestureHandlerProperties,
} from 'react-native-gesture-handler';
import type Animated from 'react-native-reanimated';
import { ANIMATION_STATE } from '../constants';
import type { ANIMATION_STATE } from '../constants';
import type { Scrollable, ScrollableRef } from '../types';
export type BottomSheetInternalContextType = {
@@ -16,7 +19,7 @@ export type BottomSheetInternalContextType = {
scrollableDecelerationRate: Animated.SharedValue<number>;
setScrollableRef: (ref: ScrollableRef) => void;
removeScrollableRef: (ref: RefObject<Scrollable>) => void;
};
} & Pick<GestureHandlerProperties, 'simultaneousHandlers' | 'waitFor'>;
// @ts-ignore
export const BottomSheetInternalContext = createContext<BottomSheetInternalContextType>();