Skip to content

Commit c60500f

Browse files
authored
feat: Add more touch events to the touchable (#378)
## Description This PR adds more callbacks to the `Sortable.Touchable` component: - `onTap`: Callback function triggered when the item is tapped - `onDoubleTap`: Callback function triggered when the item is double tapped - `onLongPress`: Callback function triggered when the item is long pressed - `onTouchesDown`: Callback function triggered when touches begin - `onTouchesUp`: Callback function triggered when touches end ## Changes showcase https://github.com/user-attachments/assets/4b4242bb-0446-4ca8-ada0-9655a37afae2
1 parent 07065b5 commit c60500f

File tree

10 files changed

+480
-215
lines changed

10 files changed

+480
-215
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { useCallback } from 'react';
2+
import { StyleSheet } from 'react-native';
3+
import { useDerivedValue, useSharedValue } from 'react-native-reanimated';
4+
import Sortable from 'react-native-sortables';
5+
6+
import {
7+
AnimatedText,
8+
Button,
9+
FlexCell,
10+
Screen,
11+
Section,
12+
Stagger
13+
} from '@/components';
14+
import { flex } from '@/theme';
15+
16+
const DATA = [
17+
'Happy 😀',
18+
'Sad 😢',
19+
'Angry 😡',
20+
'Surprised 😮',
21+
'Confused 😕',
22+
'Disappointed 😞',
23+
'Disgusted 😒',
24+
'Excited 😄',
25+
'Frustrated 😤',
26+
'Grateful 😊',
27+
'Hopeful 😊',
28+
'Joyful 😊',
29+
'Love 😊'
30+
];
31+
32+
const TEXT_LINE_HEIGHT = 16;
33+
34+
function limit<T extends Array<string>>(lines: T, maxLines: number): T {
35+
'worklet';
36+
return lines.slice(-maxLines) as T;
37+
}
38+
39+
export default function TouchableExample() {
40+
const textLines = useSharedValue<Array<string>>([]);
41+
const maxLines = useSharedValue(10);
42+
const text = useDerivedValue(() => {
43+
return textLines.value.join('\n');
44+
});
45+
46+
const onLongPress = useCallback(() => {
47+
textLines.modify(lines => {
48+
'worklet';
49+
lines.push('long press');
50+
return limit(lines, maxLines.value);
51+
});
52+
}, [textLines, maxLines]);
53+
54+
const onTap = useCallback(() => {
55+
textLines.modify(lines => {
56+
'worklet';
57+
lines.push('tap');
58+
return limit(lines, maxLines.value);
59+
});
60+
}, [textLines, maxLines]);
61+
62+
const onTouchesDown = useCallback(() => {
63+
textLines.modify(lines => {
64+
'worklet';
65+
lines.push('touches down');
66+
return limit(lines, maxLines.value);
67+
});
68+
}, [textLines, maxLines]);
69+
70+
const onTouchesUp = useCallback(() => {
71+
textLines.modify(lines => {
72+
'worklet';
73+
lines.push('touches up');
74+
return limit(lines, maxLines.value);
75+
});
76+
}, [textLines, maxLines]);
77+
78+
return (
79+
<Screen includeNavBarHeight>
80+
<Stagger wrapperStye={index => (index === 0 ? flex.fill : {})}>
81+
<Section
82+
title='Callback output'
83+
titleRight={
84+
<Button
85+
title='Clear'
86+
variant='small'
87+
onPress={() => {
88+
textLines.value = [];
89+
}}
90+
/>
91+
}
92+
animateLayout
93+
fill>
94+
<AnimatedText
95+
scrollEnabled={false}
96+
style={styles.textInput}
97+
text={text}
98+
multiline
99+
onLayout={e => {
100+
maxLines.value = Math.floor(
101+
e.nativeEvent.layout.height / TEXT_LINE_HEIGHT
102+
);
103+
}}
104+
/>
105+
</Section>
106+
107+
<Section title='Callback output' animateLayout>
108+
<Sortable.Flex
109+
dragActivationDelay={0} // drag gesture will be immediately activated
110+
gap={10}
111+
customHandle>
112+
{DATA.map(item => (
113+
<Sortable.Handle key={item}>
114+
<Sortable.Touchable
115+
onLongPress={onLongPress}
116+
onTap={onTap}
117+
onTouchesDown={onTouchesDown}
118+
onTouchesUp={onTouchesUp}>
119+
<FlexCell size='large'>{item}</FlexCell>
120+
</Sortable.Touchable>
121+
</Sortable.Handle>
122+
))}
123+
</Sortable.Flex>
124+
</Section>
125+
</Stagger>
126+
</Screen>
127+
);
128+
}
129+
130+
const styles = StyleSheet.create({
131+
textInput: {
132+
flex: 1,
133+
lineHeight: TEXT_LINE_HEIGHT
134+
}
135+
});

example/app/src/examples/SortableFlex/features/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export { default as DragHandleExample } from './DragHandleExample';
66
export { default as DropIndicatorExample } from './DropIndicatorExample';
77
export { default as FlexLayoutExample } from './FlexLayoutExample';
88
export { default as HorizontalAutoScrollExample } from './HorizontalAutoScrollExample';
9+
export { default as TouchableExample } from './TouchableExample';

example/app/src/examples/SortableFlex/tests/ZeroDelayActivationTouchableExample.tsx

Lines changed: 0 additions & 52 deletions
This file was deleted.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
export { default as ComplexLayoutExample } from './ComplexLayoutExample';
2-
export { default as ZeroDelayActivationTouchableExample } from './ZeroDelayActivationTouchableExample';
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { useCallback } from 'react';
2+
import { StyleSheet } from 'react-native';
3+
import { useDerivedValue, useSharedValue } from 'react-native-reanimated';
4+
import Sortable from 'react-native-sortables';
5+
6+
import {
7+
AnimatedText,
8+
Button,
9+
GridCard,
10+
Screen,
11+
Section,
12+
Stagger
13+
} from '@/components';
14+
import { flex, spacing } from '@/theme';
15+
import { getItems } from '@/utils';
16+
17+
const DATA = getItems(12);
18+
19+
const COLUMNS = 4;
20+
const TEXT_LINE_HEIGHT = 16;
21+
22+
function limit<T extends Array<string>>(lines: T, maxLines: number): T {
23+
'worklet';
24+
return lines.slice(-maxLines) as T;
25+
}
26+
27+
export default function TouchableExample() {
28+
const textLines = useSharedValue<Array<string>>([]);
29+
const maxLines = useSharedValue(10);
30+
const text = useDerivedValue(() => {
31+
return textLines.value.join('\n');
32+
});
33+
34+
const onLongPress = useCallback(() => {
35+
textLines.modify(lines => {
36+
'worklet';
37+
lines.push('long press');
38+
return limit(lines, maxLines.value);
39+
});
40+
}, [textLines, maxLines]);
41+
42+
const onTap = useCallback(() => {
43+
textLines.modify(lines => {
44+
'worklet';
45+
lines.push('tap');
46+
return limit(lines, maxLines.value);
47+
});
48+
}, [textLines, maxLines]);
49+
50+
const onTouchesDown = useCallback(() => {
51+
textLines.modify(lines => {
52+
'worklet';
53+
lines.push('touches down');
54+
return limit(lines, maxLines.value);
55+
});
56+
}, [textLines, maxLines]);
57+
58+
const onTouchesUp = useCallback(() => {
59+
textLines.modify(lines => {
60+
'worklet';
61+
lines.push('touches up');
62+
return limit(lines, maxLines.value);
63+
});
64+
}, [textLines, maxLines]);
65+
66+
const renderItem = useCallback(
67+
({ item }: { item: string }) => (
68+
<Sortable.Touchable
69+
onLongPress={onLongPress}
70+
onTap={onTap}
71+
onTouchesDown={onTouchesDown}
72+
onTouchesUp={onTouchesUp}>
73+
<GridCard>{item}</GridCard>
74+
</Sortable.Touchable>
75+
),
76+
[onLongPress, onTap, onTouchesDown, onTouchesUp]
77+
);
78+
79+
return (
80+
<Screen includeNavBarHeight>
81+
<Stagger wrapperStye={index => (index === 0 ? flex.fill : {})}>
82+
<Section
83+
title='Callback output'
84+
titleRight={
85+
<Button
86+
title='Clear'
87+
variant='small'
88+
onPress={() => {
89+
textLines.value = [];
90+
}}
91+
/>
92+
}
93+
animateLayout
94+
fill>
95+
<AnimatedText
96+
scrollEnabled={false}
97+
style={styles.textInput}
98+
text={text}
99+
multiline
100+
onLayout={e => {
101+
maxLines.value = Math.floor(
102+
e.nativeEvent.layout.height / TEXT_LINE_HEIGHT
103+
);
104+
}}
105+
/>
106+
</Section>
107+
108+
<Section title='Touchable Grid' animateLayout>
109+
<Sortable.Grid
110+
columnGap={spacing.xs}
111+
columns={COLUMNS}
112+
data={DATA}
113+
dragActivationDelay={0} // drag gesture will be immediately activated
114+
renderItem={renderItem}
115+
rowGap={spacing.xs}
116+
/>
117+
</Section>
118+
</Stagger>
119+
</Screen>
120+
);
121+
}
122+
123+
const styles = StyleSheet.create({
124+
textInput: {
125+
flex: 1,
126+
lineHeight: TEXT_LINE_HEIGHT
127+
}
128+
});

example/app/src/examples/SortableGrid/features/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export { default as DropIndicatorExample } from './DropIndicatorExample';
88
export { default as FixedItemsExample } from './FixedItemsExample';
99
export { default as HorizontalAutoScrollExample } from './HorizontalAutoScrollExample';
1010
export { default as OrderingStrategyExample } from './OrderingStrategyExample';
11+
export { default as TouchableExample } from './TouchableExample';

example/app/src/examples/navigation/routes.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,15 @@ const routes: Routes = {
5151
Component: SortableGrid.features.FixedItemsExample,
5252
name: 'Fixed Items'
5353
},
54-
CallbacksExample: {
54+
Callbacks: {
5555
Component: SortableGrid.features.CallbacksExample,
5656
name: 'Callbacks'
5757
},
58-
DebugExample: {
58+
Touchable: {
59+
Component: SortableGrid.features.TouchableExample,
60+
name: 'Touchable'
61+
},
62+
Debug: {
5963
Component: SortableGrid.features.DebugExample,
6064
name: 'Debug'
6165
}
@@ -110,11 +114,15 @@ const routes: Routes = {
110114
Component: SortableFlex.features.HorizontalAutoScrollExample,
111115
name: 'Horizontal Auto Scroll'
112116
},
113-
CallbacksExample: {
117+
Callbacks: {
114118
Component: SortableFlex.features.CallbacksExample,
115119
name: 'Callbacks'
116120
},
117-
DebugExample: {
121+
Touchable: {
122+
Component: SortableFlex.features.TouchableExample,
123+
name: 'Touchable'
124+
},
125+
Debug: {
118126
Component: SortableFlex.features.DebugExample,
119127
name: 'Debug'
120128
}
@@ -126,10 +134,6 @@ const routes: Routes = {
126134
ComplexLayout: {
127135
Component: SortableFlex.tests.ComplexLayoutExample,
128136
name: 'Complex Layout'
129-
},
130-
ZeroDelayActivationTouchableExample: {
131-
Component: SortableFlex.tests.ZeroDelayActivationTouchableExample,
132-
name: 'Zero Delay Activation Touchable'
133137
}
134138
}
135139
}

0 commit comments

Comments
 (0)