Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dad2eaa
new file
m-bert Nov 3, 2025
6dbc10d
use native
m-bert Nov 3, 2025
4f1dcaa
Buttons
m-bert Nov 3, 2025
8ccf267
Remove Reanimated
m-bert Nov 3, 2025
df3f1fb
Components
m-bert Nov 4, 2025
a1da35a
Add proper values to relations
m-bert Nov 4, 2025
a680461
Bring back old components
m-bert Nov 4, 2025
a0d0240
Deprecate legacy buttons
m-bert Nov 4, 2025
ef1e736
Deprecate legacy components
m-bert Nov 4, 2025
563fab3
Export new components
m-bert Nov 4, 2025
0f40c58
Add web file
m-bert Nov 4, 2025
13951df
Merge branch 'next' into @mbert/components-new-api
m-bert Nov 4, 2025
b77cc2b
Update import
m-bert Nov 4, 2025
c336453
use ref in check
m-bert Nov 4, 2025
c3f4320
Correct refs
m-bert Nov 4, 2025
c6c83ba
Merge branch 'next' into @mbert/components-new-api
m-bert Nov 12, 2025
86c38f3
Merge branch 'next' into @mbert/components-new-api
m-bert Nov 13, 2025
baf7eb1
Merge branch 'next' into @mbert/components-new-api
m-bert Nov 14, 2025
c8f7c8c
Add examples
m-bert Nov 14, 2025
2a356f8
Fix buttons
m-bert Nov 14, 2025
73969da
Yet another fix
m-bert Nov 14, 2025
f4fa5f6
Remove Drawer Layout
m-bert Nov 14, 2025
ede51fe
Impoort hooks directly
m-bert Nov 15, 2025
d34ef86
remove import
m-bert Nov 15, 2025
fdf9533
Update examples
m-bert Nov 15, 2025
38f36fe
Merge branch 'next' into @mbert/components-new-api
m-bert Nov 17, 2025
25bd430
Update scroll example
m-bert Nov 18, 2025
4c5eaf8
Correctly attach NativeViewGestureHandler
m-bert Nov 18, 2025
36d1afb
Fix relations in ScrollView
m-bert Nov 18, 2025
11eeef1
FlatList
m-bert Nov 19, 2025
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
12 changes: 12 additions & 0 deletions apps/common-app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ import LongPressExample from './src/simple/longPress';
import ManualExample from './src/simple/manual';
import SimpleFling from './src/simple/fling';

import FlatListExample from './src/components/flatlist';
import ScrollViewExample from './src/components/scrollview';
import ButtonsExample from './src/components/buttons';

import { Icon } from '@swmansion/icons';

interface Example {
Expand Down Expand Up @@ -114,6 +118,14 @@ const EXAMPLES: ExamplesSection[] = [
},
],
},
{
sectionTitle: 'Components',
data: [
{ name: 'FlatList example', component: FlatListExample },
{ name: 'ScrollView example', component: ScrollViewExample },
{ name: 'Buttons example', component: ButtonsExample },
],
},
{
sectionTitle: 'Basic examples',
data: [
Expand Down
10 changes: 5 additions & 5 deletions apps/common-app/src/basic/pagerAndDrawer/index.android.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {
createNativeWrapper,
DrawerLayoutAndroid,
LegacyDrawerLayoutAndroid,
} from 'react-native-gesture-handler';

const WrappedViewPagerAndroid = createNativeWrapper(ViewPagerAndroid, {
Expand Down Expand Up @@ -35,22 +35,22 @@ export default class Example extends Component {
return (
<WrappedViewPagerAndroid style={styles.container}>
<View>
<DrawerLayoutAndroid
<LegacyDrawerLayoutAndroid
drawerWidth={200}
drawerPosition="left"
renderNavigationView={() => navigationView}>
<Page backgroundColor="gray" text="First 🙈" />
</DrawerLayoutAndroid>
</LegacyDrawerLayoutAndroid>
</View>
<Page backgroundColor="yellow" text="Second 🙉" />
<Page backgroundColor="blue" text="Third 🙊" />
<View>
<DrawerLayoutAndroid
<LegacyDrawerLayoutAndroid
drawerWidth={200}
drawerPosition="right"
renderNavigationView={() => navigationView}>
<Page backgroundColor="blue" text="Fourth 😎" />
</DrawerLayoutAndroid>
</LegacyDrawerLayoutAndroid>
</View>
</WrappedViewPagerAndroid>
);
Expand Down
61 changes: 61 additions & 0 deletions apps/common-app/src/components/buttons/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { StyleSheet, Text } from 'react-native';
import {
BaseButton,
BorderlessButton,
GestureHandlerRootView,
RectButton,
} from 'react-native-gesture-handler';

type ButtonWrapperProps = {
ButtonComponent:
| typeof BaseButton
| typeof RectButton
| typeof BorderlessButton;

color: string;
};

function ButtonWrapper({ ButtonComponent, color }: ButtonWrapperProps) {
return (
<ButtonComponent
style={[styles.button, { backgroundColor: color }]}
onPress={() => console.log(`[${ButtonComponent.name}] onPress`)}
onLongPress={() => {
console.log(`[${ButtonComponent.name}] onLongPress`);
}}>
<Text style={styles.buttonText}>{ButtonComponent.name}</Text>
</ButtonComponent>
);
}

export default function ButtonsExample() {
return (
<GestureHandlerRootView style={styles.container}>
<ButtonWrapper ButtonComponent={BaseButton} color="#2196F3" />
<ButtonWrapper ButtonComponent={RectButton} color="#f44336" />
<ButtonWrapper ButtonComponent={BorderlessButton} color="#ff9800" />
</GestureHandlerRootView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'space-around',
},
button: {
width: 200,
height: 50,
borderRadius: 15,

display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
},

buttonText: {
color: 'white',
fontSize: 16,
},
});
44 changes: 44 additions & 0 deletions apps/common-app/src/components/flatlist/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { FlatList, GestureHandlerRootView } from 'react-native-gesture-handler';

const DATA = Array.from({ length: 20 }, (_, i) => ({
id: i.toString(),
title: `Item ${i + 1}`,
}));

const Item = ({ title }: { title: string }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);

export default function FlatListExample() {
return (
<GestureHandlerRootView>
<FlatList
data={DATA}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <Item title={item.title} />}
contentContainerStyle={styles.container}
/>
;
</GestureHandlerRootView>
);
}

const styles = StyleSheet.create({
container: {
paddingVertical: 16,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
borderRadius: 8,
},
title: {
fontSize: 18,
},
});
53 changes: 53 additions & 0 deletions apps/common-app/src/components/scrollview/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { useState } from 'react';
import { Text, StyleSheet, View } from 'react-native';
import { ScrollView, RefreshControl } from 'react-native-gesture-handler';

const DATA = Array.from({ length: 20 }, (_, i) => ({
id: i.toString(),
title: `Item ${i + 1}`,
}));

const Item = ({ title }: { title: string }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);

export default function ScrollViewExample() {
const [refreshing, setRefreshing] = useState(false);

const onRefresh = () => {
setRefreshing(true);
setTimeout(() => {
setRefreshing(false);
}, 1500);
};

return (
<ScrollView
contentContainerStyle={styles.container}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}>
{DATA.map((item) => (
<Item key={item.id} title={item.title} />
))}
</ScrollView>
);
}

const styles = StyleSheet.create({
container: {
padding: 24,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
borderRadius: 8,
},
title: {
fontSize: 18,
},
});
10 changes: 5 additions & 5 deletions apps/common-app/src/new_api/calculator/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import {
GestureDetector,
Gesture,
ScrollView,
LegacyScrollView,
} from 'react-native-gesture-handler';
import Animated, {
useSharedValue,
Expand Down Expand Up @@ -60,7 +60,7 @@ interface OutputProps {

function Output({ offset, expression, history }: OutputProps) {
const layout = useRef({});
const scrollView = useRef<ScrollView>(null);
const scrollView = useRef<LegacyScrollView>(null);
const drag = useSharedValue(0);
const dragOffset = useSharedValue(0);
const [opened, setOpened] = useState(false);
Expand Down Expand Up @@ -130,8 +130,8 @@ function Output({ offset, expression, history }: OutputProps) {
<Animated.View
style={[styles.output, translationStyle]}
onLayout={measure}>
<ScrollView
ref={(ref: ScrollView) => {
<LegacyScrollView
ref={(ref: LegacyScrollView) => {
if (!opened) {
ref?.scrollToEnd({ animated: false });
}
Expand All @@ -146,7 +146,7 @@ function Output({ offset, expression, history }: OutputProps) {
})}

<Expression expression={expression} />
</ScrollView>
</LegacyScrollView>
<View style={styles.handleView}>
<View style={styles.handle} />
</View>
Expand Down
6 changes: 3 additions & 3 deletions apps/common-app/src/recipes/panAndScroll/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { Animated, Dimensions, StyleSheet } from 'react-native';
import {
PanGestureHandler,
TapGestureHandler,
ScrollView,
State,
PanGestureHandlerGestureEvent,
TapGestureHandlerStateChangeEvent,
LegacyScrollView,
} from 'react-native-gesture-handler';

import { USE_NATIVE_DRIVER } from '../../config';
Expand Down Expand Up @@ -92,11 +92,11 @@ export default class Example extends Component {
const tapRef = React.createRef<TapGestureHandler>();
const panRef = React.createRef<PanGestureHandler>();
return (
<ScrollView waitFor={[tapRef, panRef]}>
<LegacyScrollView waitFor={[tapRef, panRef]}>
<LoremIpsum words={150} />
<TapOrPan tapRef={tapRef} panRef={panRef} />
<LoremIpsum words={150} />
</ScrollView>
</LegacyScrollView>
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.facebook.react.bridge.ReadableType
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.bridge.WritableArray
import com.facebook.react.uimanager.PixelUtil
import com.facebook.react.views.swiperefresh.ReactSwipeRefreshLayout
import com.swmansion.gesturehandler.BuildConfig
import com.swmansion.gesturehandler.RNSVGHitTester
import com.swmansion.gesturehandler.react.RNGestureHandlerDetectorView
Expand Down Expand Up @@ -47,7 +48,13 @@ open class GestureHandler {
) {
this.hostDetectorView
} else if (this is NativeViewGestureHandler) {
this.view?.parent
val parent = this.view?.parent

if (parent is ReactSwipeRefreshLayout) {
parent.parent
} else {
parent
}
} else {
view
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.facebook.react.bridge.ReadableArray
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.events.Event
import com.facebook.react.views.swiperefresh.ReactSwipeRefreshLayout
import com.facebook.react.views.view.ReactViewGroup
import com.swmansion.gesturehandler.core.GestureHandler

Expand Down Expand Up @@ -67,7 +68,7 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
override fun addView(child: View, index: Int, params: LayoutParams?) {
super.addView(child, index, params)

tryAttachNativeHandlersToChildView(child.id)
tryAttachNativeHandlersToChildView(child)
}

override fun removeViewAt(index: Int) {
Expand Down Expand Up @@ -114,7 +115,7 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {

// This covers the case where `NativeViewGestureHandlers` are attached after child views were created.
if (child != null) {
tryAttachNativeHandlersToChildView(child.id)
tryAttachNativeHandlersToChildView(child)
}
}

Expand Down Expand Up @@ -149,12 +150,19 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
}
}

private fun tryAttachNativeHandlersToChildView(childId: Int) {
private fun tryAttachNativeHandlersToChildView(child: View) {
val registry = RNGestureHandlerModule.registries[moduleId]
?: throw Exception("Tried to access a non-existent registry")

val id = if (child is ReactSwipeRefreshLayout) {
child.getChildAt(0).id
} else {
child.id
}

for (tag in nativeHandlers) {
registry.attachHandlerToView(tag, childId, GestureHandler.ACTION_TYPE_NATIVE_DETECTOR)
// registry.attachHandlerToView(tag, id, GestureHandler.ACTION_TYPE_NATIVE_DETECTOR)
registry.attachHandlerToView(tag, id, GestureHandler.ACTION_TYPE_NATIVE_DETECTOR)

attachedHandlers.add(tag)
}
Expand Down
Loading
Loading