Use @gorhom/bottom-sheet for waypoint sheet
Replace custom View-based bottom sheet with @gorhom/bottom-sheet: - Native gesture-driven drag, snap points, pan-down-to-close - Proper safe area handling built in - Wrap app with GestureHandlerRootView - Add react-native-reanimated plugin to Expo config Adds react-native-reanimated and react-native-gesture-handler as native dependencies (requires new EAS build). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fe07fbdf59
commit
bdde95e69b
6 changed files with 782 additions and 250 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { View, Text, TouchableOpacity, StyleSheet, Alert } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { useRef, useCallback, useMemo } from "react";
|
||||
import { Text, TouchableOpacity, StyleSheet, Alert } from "react-native";
|
||||
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
|
||||
import type { Waypoint } from "@trails-cool/types";
|
||||
|
||||
interface WaypointSheetProps {
|
||||
|
|
@ -17,9 +18,10 @@ export function WaypointSheet({
|
|||
onDelete,
|
||||
onToggleOvernight,
|
||||
}: WaypointSheetProps) {
|
||||
const insets = useSafeAreaInsets();
|
||||
const bottomSheetRef = useRef<BottomSheet>(null);
|
||||
const snapPoints = useMemo(() => ["35%"], []);
|
||||
|
||||
const handleDelete = () => {
|
||||
const handleDelete = useCallback(() => {
|
||||
Alert.alert(
|
||||
"Delete Waypoint",
|
||||
`Remove waypoint ${index + 1}${waypoint.name ? ` (${waypoint.name})` : ""}?`,
|
||||
|
|
@ -35,63 +37,55 @@ export function WaypointSheet({
|
|||
},
|
||||
],
|
||||
);
|
||||
};
|
||||
}, [index, waypoint.name, onDelete, onClose]);
|
||||
|
||||
const handleSheetChange = useCallback((sheetIndex: number) => {
|
||||
if (sheetIndex === -1) onClose();
|
||||
}, [onClose]);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { paddingBottom: 16 + insets.bottom }]}>
|
||||
<View style={styles.handle} />
|
||||
<Text style={styles.title}>
|
||||
Waypoint {index + 1}{waypoint.name ? `: ${waypoint.name}` : ""}
|
||||
</Text>
|
||||
<Text style={styles.coords}>
|
||||
{waypoint.lat.toFixed(5)}, {waypoint.lon.toFixed(5)}
|
||||
</Text>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.option}
|
||||
onPress={() => {
|
||||
onToggleOvernight(index);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<Text style={styles.optionIcon}>{waypoint.isDayBreak ? "☀️" : "🌙"}</Text>
|
||||
<Text style={styles.optionText}>
|
||||
{waypoint.isDayBreak ? "Remove overnight stop" : "Mark as overnight stop"}
|
||||
<BottomSheet
|
||||
ref={bottomSheetRef}
|
||||
snapPoints={snapPoints}
|
||||
enablePanDownToClose
|
||||
onChange={handleSheetChange}
|
||||
backgroundStyle={styles.background}
|
||||
handleIndicatorStyle={styles.handle}
|
||||
>
|
||||
<BottomSheetView style={styles.content}>
|
||||
<Text style={styles.title}>
|
||||
Waypoint {index + 1}{waypoint.name ? `: ${waypoint.name}` : ""}
|
||||
</Text>
|
||||
<Text style={styles.coords}>
|
||||
{waypoint.lat.toFixed(5)}, {waypoint.lon.toFixed(5)}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.option} onPress={handleDelete}>
|
||||
<Text style={styles.optionIcon}>🗑️</Text>
|
||||
<Text style={[styles.optionText, styles.deleteText]}>Delete waypoint</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.option}
|
||||
onPress={() => {
|
||||
onToggleOvernight(index);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<Text style={styles.optionIcon}>{waypoint.isDayBreak ? "☀️" : "🌙"}</Text>
|
||||
<Text style={styles.optionText}>
|
||||
{waypoint.isDayBreak ? "Remove overnight stop" : "Mark as overnight stop"}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.closeButton} onPress={onClose}>
|
||||
<Text style={styles.closeText}>Close</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<TouchableOpacity style={styles.option} onPress={handleDelete}>
|
||||
<Text style={styles.optionIcon}>🗑️</Text>
|
||||
<Text style={[styles.optionText, styles.deleteText]}>Delete waypoint</Text>
|
||||
</TouchableOpacity>
|
||||
</BottomSheetView>
|
||||
</BottomSheet>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: "#fff",
|
||||
borderTopLeftRadius: 16,
|
||||
borderTopRightRadius: 16,
|
||||
padding: 16,
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: -2 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 8,
|
||||
elevation: 5,
|
||||
},
|
||||
handle: {
|
||||
width: 36,
|
||||
height: 4,
|
||||
borderRadius: 2,
|
||||
backgroundColor: "#d1d5db",
|
||||
alignSelf: "center",
|
||||
marginBottom: 12,
|
||||
},
|
||||
background: { borderTopLeftRadius: 16, borderTopRightRadius: 16 },
|
||||
handle: { backgroundColor: "#d1d5db", width: 36 },
|
||||
content: { padding: 16 },
|
||||
title: { fontSize: 16, fontWeight: "600", color: "#111" },
|
||||
coords: { fontSize: 12, color: "#999", marginTop: 2, marginBottom: 16 },
|
||||
option: {
|
||||
|
|
@ -104,12 +98,4 @@ const styles = StyleSheet.create({
|
|||
optionIcon: { fontSize: 18, marginRight: 12 },
|
||||
optionText: { fontSize: 15, color: "#333" },
|
||||
deleteText: { color: "#dc2626" },
|
||||
closeButton: {
|
||||
marginTop: 12,
|
||||
alignItems: "center",
|
||||
paddingVertical: 12,
|
||||
backgroundColor: "#f3f4f6",
|
||||
borderRadius: 8,
|
||||
},
|
||||
closeText: { fontSize: 15, color: "#666" },
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue