Skip to content

Commit 5713701

Browse files
EvanBaconkmagiera
authored andcommitted
Web Support (software-mansion#555)
# Why Using hammer.js to emulate the native gesture API. Ideally we'll reuse as much API logic as possible between native and web. # TODO ## Components - [x] `ScrollView` - [ ] `Switch` - [ ] `TextInput` - [ ] `ToolbarAndroid` - [ ] `DrawerLayoutAndroid` - [ ] `FlatList` - [x] `Swipeable` ## Gesture Handlers - [x] `PanGestureHandler` - [x] `RotationGestureHandler` - [x] `PinchGestureHandler` - [x] `TapGestureHandler` - [x] `NativeViewGestureHandler` - [x] `LongPressGestureHandler` - [ ] `ForceTouchGestureHandler` - [x] `FlingGestureHandler` ### Props - [x] `waitFor` - [x] `shouldCancelWhenOutside` ### Native View Gesture Handler - [x] Delay content touches - [x] Disallow Interruptions ## Buttons - [x] `RawButton` - [x] `BaseButton` - [x] `RectButton` - [x] `BorderlessButton` - [x] `PureNativeButton` # Test Plan TBD. Running in NCL by cloning into the [expo/expo](https://github.com/expo/expo) repo `packages/`. ![expo hammer-low](https://user-images.githubusercontent.com/9664363/55779912-97fd6280-5a5b-11e9-83a3-010f272256f5.gif) lol disregard frame-rate, it's smooth IRL.
1 parent 4728063 commit 5713701

26 files changed

+1531
-236
lines changed

Directions.web.js

-6
This file was deleted.

GestureHandlerButton.web.js

+2-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
import React from 'react';
2-
import { TouchableOpacity } from 'react-native';
2+
import { View } from 'react-native';
33

4-
// Use TouchableOpacity with the transparency disabled to most closely emulate
5-
// the native view's ability to wrap children and apply styles.
64
export default React.forwardRef((props, ref) => (
7-
<TouchableOpacity
8-
ref={ref}
9-
accessibilityRole="button"
10-
{...props}
11-
activeOpacity={1.0}
12-
focusOpacity={1.0}
13-
/>
5+
<View ref={ref} accessibilityRole="button" {...props} />
146
));

RNGestureHandlerModule.web.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Direction } from './web/constants';
2+
import FlingGestureHandler from './web/FlingGestureHandler';
3+
import LongPressGestureHandler from './web/LongPressGestureHandler';
4+
import NativeViewGestureHandler from './web/NativeViewGestureHandler';
5+
import * as NodeManager from './web/NodeManager';
6+
import PanGestureHandler from './web/PanGestureHandler';
7+
import PinchGestureHandler from './web/PinchGestureHandler';
8+
import RotationGestureHandler from './web/RotationGestureHandler';
9+
import TapGestureHandler from './web/TapGestureHandler';
10+
11+
const Gestures = {
12+
PanGestureHandler,
13+
RotationGestureHandler,
14+
PinchGestureHandler,
15+
TapGestureHandler,
16+
NativeViewGestureHandler,
17+
LongPressGestureHandler,
18+
FlingGestureHandler,
19+
// ForceTouchGestureHandler,
20+
};
21+
22+
export default {
23+
Direction,
24+
handleSetJSResponder(tag, blockNativeResponder) {
25+
console.warn('handleSetJSResponder: ', tag, blockNativeResponder);
26+
},
27+
handleClearJSResponder() {
28+
console.warn('handleClearJSResponder: ');
29+
},
30+
createGestureHandler(handlerName, handlerTag, config) {
31+
if (!(handlerName in Gestures))
32+
throw new Error(`react-native-gesture-handler: ${handlerName} is not supported on web.`);
33+
const GestureClass = Gestures[handlerName];
34+
NodeManager.createGestureHandler(handlerTag, new GestureClass());
35+
this.updateGestureHandler(handlerTag, config);
36+
},
37+
attachGestureHandler(handlerTag, newView) {
38+
NodeManager.getHandler(handlerTag).setView(newView);
39+
},
40+
updateGestureHandler(handlerTag, newConfig) {
41+
NodeManager.getHandler(handlerTag).updateGestureConfig(newConfig);
42+
},
43+
getGestureHandlerNode(handlerTag) {
44+
return NodeManager.getHandler(handlerTag);
45+
},
46+
dropGestureHandler(handlerTag) {
47+
NodeManager.dropGestureHandler(handlerTag);
48+
},
49+
};

Swipeable.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,9 @@ export default class Swipeable extends Component<PropType, StateType> {
315315
minDeltaX={10}
316316
onGestureEvent={this._onGestureEvent}
317317
onHandlerStateChange={this._onHandlerStateChange}>
318-
<Animated.View onLayout={this._onRowLayout} style={[styles.container, this.props.containerStyle]}>
318+
<Animated.View
319+
onLayout={this._onRowLayout}
320+
style={[styles.container, this.props.containerStyle]}>
319321
{left}
320322
{right}
321323
<TapGestureHandler
@@ -327,7 +329,7 @@ export default class Swipeable extends Component<PropType, StateType> {
327329
{
328330
transform: [{ translateX: this._transX }],
329331
},
330-
this.props.childrenContainerStyle
332+
this.props.childrenContainerStyle,
331333
]}>
332334
{children}
333335
</Animated.View>

Swipeable.web.js

-4
This file was deleted.

createHandler.js

+18-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import React from 'react';
2-
import { findNodeHandle, NativeModules, Touchable } from 'react-native';
2+
import {
3+
findNodeHandle as findNodeHandleRN,
4+
NativeModules,
5+
Touchable,
6+
Platform,
7+
} from 'react-native';
38
import deepEqual from 'fbjs/lib/areEqual';
49
import RNGestureHandlerModule from './RNGestureHandlerModule';
5-
610
import State from './State';
711

8-
const { UIManager } = NativeModules;
12+
function findNodeHandle(node) {
13+
if (Platform.OS === 'web') return node;
14+
return findNodeHandleRN(node);
15+
}
16+
17+
const { UIManager = {} } = NativeModules;
918

1019
const customGHEventsConfig = {
1120
onGestureHandlerEvent: { registrationName: 'onGestureHandlerEvent' },
@@ -25,9 +34,9 @@ UIManager.genericDirectEventTypes = {
2534

2635
// Wrap JS responder calls and notify gesture handler manager
2736
const {
28-
setJSResponder: oldSetJSResponder,
29-
clearJSResponder: oldClearJSResponder,
30-
getConstants: oldGetConstants,
37+
setJSResponder: oldSetJSResponder = () => {},
38+
clearJSResponder: oldClearJSResponder = () => {},
39+
getConstants: oldGetConstants = () => ({}),
3140
} = UIManager;
3241
UIManager.setJSResponder = (tag, blockNativeResponder) => {
3342
RNGestureHandlerModule.handleSetJSResponder(tag, blockNativeResponder);
@@ -88,6 +97,9 @@ function transformIntoHandlerTags(handlerIDs) {
8897
handlerIDs = [handlerIDs];
8998
}
9099

100+
if (Platform.OS === 'web') {
101+
return handlerIDs.map(({ current }) => current).filter(handle => handle);
102+
}
91103
// converts handler string IDs into their numeric tags
92104
return handlerIDs
93105
.map(

createHandler.web.js

-205
This file was deleted.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
"android/lib/build.gradle",
1717
"android/lib/src/main/java/",
1818
"ios/",
19+
"web/",
1920
"__mocks__/",
2021
"touchables/**/*.js",
2122
"createHandler.js",
2223
"createHandler.web.js",
2324
"Directions.js",
24-
"Directions.web.js",
2525
"DrawerLayout.js",
2626
"GestureHandler.js",
2727
"Gestures.js",
@@ -63,6 +63,7 @@
6363
},
6464
"homepage": "https://github.com/kmagiera/react-native-gesture-handler#readme",
6565
"dependencies": {
66+
"hammerjs": "^2.0.8",
6667
"hoist-non-react-statics": "^2.3.1",
6768
"invariant": "^2.2.2",
6869
"prop-types": "^15.5.10"

touchables/GenericTouchable.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,9 @@ export default class GenericTouchable extends Component {
256256

257257
return (
258258
<BaseButton
259-
onHandlerStateChange={this.props.disabled ? null : this.onHandlerStateChange}
259+
onHandlerStateChange={
260+
this.props.disabled ? null : this.onHandlerStateChange
261+
}
260262
onGestureEvent={this.onGestureEvent}
261263
hitSlop={this.props.hitSlop}
262264
{...this.props.extraButtonProps}>

0 commit comments

Comments
 (0)