Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/basic-example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
import ContentsButton from './ContentsButton';
import NativeDetector from './NativeDetector';
import Navigator from './Navigator';
import PointerEventsRepro from './PointerEventsRepro';
import RuntimeDecoration from './RuntimeDecoration';
import Text from './Text';

Expand All @@ -25,6 +26,10 @@ const EXAMPLES = [
name: 'Contents Button',
component: ContentsButton,
},
{
name: 'Root Pointer Events',
component: PointerEventsRepro,
},
];

const Stack = Navigator.create();
Expand Down
102 changes: 102 additions & 0 deletions apps/basic-example/src/PointerEventsRepro.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import * as React from 'react';
import {
Button,
Pressable,
StyleSheet,
Text,
View,
type ViewProps,
} from 'react-native';
import {
GestureDetector,
GestureHandlerRootView,
useTapGesture,
} from 'react-native-gesture-handler';

export default function PointerEventsRepro() {
const [mode, setMode] =
React.useState<ViewProps['pointerEvents']>('box-none');
const [plain, setPlain] = React.useState(false);
const [background, setBackground] = React.useState(0);
const [child, setChild] = React.useState(0);
const [gesture, setGesture] = React.useState(0);
const tap = useTapGesture({
runOnJS: true,
onActivate: () => setGesture((n) => n + 1),
});
const Wrapper = plain ? View : GestureHandlerRootView;
return (
<GestureHandlerRootView style={styles.screen}>
<Text>Root pointerEvents regression</Text>
<Text testID="status">
{plain ? 'View' : 'Root'} / {mode ?? 'unset'} / background {background}{' '}
/ child {child} / gesture {gesture}
</Text>
<Button
title={plain ? 'Use Root' : 'Use View'}
onPress={() => setPlain(!plain)}
/>
<View style={styles.controls}>
{(['auto', 'none', 'box-only', 'box-none', undefined] as const).map(
(value) => (
<Button
key={value ?? 'unset'}
title={value ?? 'unset'}
onPress={() => setMode(value)}
/>
)
)}
</View>
<Button
title="Reset counts"
onPress={() => {
setBackground(0);
setChild(0);
setGesture(0);
}}
/>
<View style={styles.area}>
<Pressable
accessibilityLabel="Background"
style={StyleSheet.absoluteFill}
onPress={() => setBackground((n) => n + 1)}>
<Text style={{ marginTop: 250 }}>Background</Text>
</Pressable>
<Wrapper pointerEvents={mode} style={styles.overlay}>
<View pointerEvents="none" style={styles.side}>
<Text>Empty side</Text>
</View>
<Pressable
accessibilityLabel="Child press"
style={styles.child}
onPress={() => setChild((n) => n + 1)}>
<Text>Child press</Text>
</Pressable>
<GestureDetector gesture={tap}>
<View
accessible
accessibilityLabel="Child gesture"
style={styles.child}>
<Text>Child gesture</Text>
</View>
</GestureDetector>
</Wrapper>
</View>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, paddingTop: 48, backgroundColor: 'white' },
controls: { flexDirection: 'row', flexWrap: 'wrap' },
area: { height: 350, margin: 16, backgroundColor: '#ddf' },
overlay: { height: 230, backgroundColor: '#fdd8', alignItems: 'center' },
side: { position: 'absolute', left: 4, top: 90, width: 70 },
child: {
width: 160,
height: 75,
margin: 12,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#9d9',
},
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.swmansion.gesturehandler.react

import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.PointerEvents.Companion.parsePointerEvents
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.ViewManagerDelegate
Expand Down Expand Up @@ -39,6 +40,11 @@ class RNGestureHandlerRootViewManager :
view.setModuleId(value)
}

@ReactProp(name = "pointerEvents")
override fun setPointerEvents(view: RNGestureHandlerRootView, pointerEventsStr: String?) {
view.pointerEvents = parsePointerEvents(pointerEventsStr)
}

@ReactProp(name = "unstable_forceActive")
override fun setUnstable_forceActive(view: RNGestureHandlerRootView, active: Boolean) {
view.setUnstableForceActive(active)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export interface RootViewNativeProps extends ViewProps {
unstable_forceActive?: boolean;
}

// @ts-expect-error WithDefault adds null for codegen, unlike ViewProps.pointerEvents.
interface NativeProps extends ViewProps {
pointerEvents?: CodegenTypes.WithDefault<
'box-none' | 'none' | 'box-only' | 'auto',
'auto'
>;
moduleId?: CodegenTypes.WithDefault<CodegenTypes.Int32, -1>;
unstable_forceActive?: boolean;
}
Expand Down