UNPKG

expo-osm-sdk

Version:

OpenStreetMap component for React Native with Expo

251 lines 9.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NavigationControls = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const react_native_1 = require("react-native"); /** * NavigationControls - Clean map navigation controls * Provides zoom, compass, and pitch controls in a vertical stack * * @example * <NavigationControls * onZoomIn={() => mapRef.current?.zoomIn()} * onZoomOut={() => mapRef.current?.zoomOut()} * onResetBearing={() => mapRef.current?.setBearing(0)} * onResetPitch={() => mapRef.current?.setPitch(0)} * bearing={bearing} * pitch={pitch} * /> */ const NavigationControls = ({ onZoomIn, onZoomOut, onResetBearing, onResetPitch, bearing = 0, pitch = 0, style, size = 40, color = '#9C1AFF', showPitchControl = true, showCompassControl = true, getBearing, getPitch, }) => { const [currentBearing, setCurrentBearing] = (0, react_1.useState)(bearing); const [currentPitch, setCurrentPitch] = (0, react_1.useState)(pitch); // Update bearing from props or fetch (0, react_1.useEffect)(() => { if (bearing !== undefined) { setCurrentBearing(bearing); } else if (getBearing) { getBearing().then(setCurrentBearing).catch(() => { }); } }, [bearing, getBearing]); // Update pitch from props or fetch (0, react_1.useEffect)(() => { if (pitch !== undefined) { setCurrentPitch(pitch); } else if (getPitch) { getPitch().then(setCurrentPitch).catch(() => { }); } }, [pitch, getPitch]); const handleResetBearing = async () => { onResetBearing?.(); if (getBearing) { // Update after a short delay to show the change setTimeout(async () => { const newBearing = await getBearing(); setCurrentBearing(newBearing); }, 100); } }; const handleResetPitch = async () => { onResetPitch?.(); if (getPitch) { setTimeout(async () => { const newPitch = await getPitch(); setCurrentPitch(newPitch); }, 100); } }; const is3DMode = currentPitch > 5; // Consider 3D if pitch > 5 degrees return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [styles.container, { width: size }, style], children: [(0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: onZoomIn, style: [ styles.button, styles.topButton, { width: size, height: size }, ], activeOpacity: 0.7, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [styles.plusIcon, { backgroundColor: color }], children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.plusVertical, { backgroundColor: '#FFFFFF' }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.plusHorizontal, { backgroundColor: '#FFFFFF' }] })] }) }), (0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: onZoomOut, style: [ styles.button, styles.middleButton, { width: size, height: size }, ], activeOpacity: 0.7, children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.minusIcon, { backgroundColor: color }], children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.minusLine, { backgroundColor: '#FFFFFF' }] }) }) }), showCompassControl && ((0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: handleResetBearing, style: [ styles.button, showPitchControl ? styles.middleButton : styles.bottomButton, { width: size, height: size }, ], activeOpacity: 0.7, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [ styles.compassIcon, { transform: [{ rotate: `${-currentBearing}deg` }] }, ], children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.compassCircle }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.compassNeedleNorth, { borderBottomColor: color }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.compassNeedleSouth, { borderTopColor: `${color}80` }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.compassCenter, { backgroundColor: color }] })] }) })), showPitchControl && ((0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: handleResetPitch, style: [ styles.button, styles.bottomButton, { width: size, height: size }, is3DMode && { backgroundColor: `${color}10` }, ], activeOpacity: 0.7, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: styles.pitchIcon, children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.pitchCircle }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.chevronUp, { borderBottomColor: color }] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.chevronDown, { borderTopColor: color }] })] }) }))] })); }; exports.NavigationControls = NavigationControls; const styles = react_native_1.StyleSheet.create({ container: { gap: 1, }, button: { backgroundColor: '#FFFFFF', borderWidth: 0, // Borderless as requested justifyContent: 'center', alignItems: 'center', ...react_native_1.Platform.select({ ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.15, shadowRadius: 3, }, android: { elevation: 4, }, }), }, topButton: { borderTopLeftRadius: 4, borderTopRightRadius: 4, }, middleButton: { borderRadius: 0, }, bottomButton: { borderBottomLeftRadius: 4, borderBottomRightRadius: 4, }, // Plus icon (Zoom In) plusIcon: { width: 20, height: 20, borderRadius: 10, justifyContent: 'center', alignItems: 'center', }, plusVertical: { position: 'absolute', width: 2, height: 10, }, plusHorizontal: { position: 'absolute', width: 10, height: 2, }, // Minus icon (Zoom Out) minusIcon: { width: 20, height: 20, borderRadius: 10, justifyContent: 'center', alignItems: 'center', }, minusLine: { width: 10, height: 2, }, // Compass icon (Compass needle with circle) compassIcon: { width: 24, height: 24, justifyContent: 'center', alignItems: 'center', position: 'relative', }, compassCircle: { width: 20, height: 20, borderRadius: 10, borderWidth: 2, borderColor: '#FFFFFF', position: 'absolute', }, compassNeedleNorth: { width: 0, height: 0, backgroundColor: 'transparent', borderStyle: 'solid', borderLeftWidth: 3, borderRightWidth: 3, borderTopWidth: 0, borderBottomWidth: 6, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderTopColor: 'transparent', position: 'absolute', top: 4, left: 9, }, compassNeedleSouth: { width: 0, height: 0, backgroundColor: 'transparent', borderStyle: 'solid', borderLeftWidth: 3, borderRightWidth: 3, borderBottomWidth: 0, borderTopWidth: 4, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderBottomColor: 'transparent', position: 'absolute', top: 10, left: 9, }, compassCenter: { width: 3, height: 3, borderRadius: 1.5, position: 'absolute', top: 10.5, left: 10.5, }, // Pitch icon (Two chevron arrows with white circle background) pitchIcon: { width: 24, height: 24, justifyContent: 'center', alignItems: 'center', position: 'relative', }, pitchCircle: { width: 20, height: 20, borderRadius: 10, backgroundColor: '#FFFFFF', position: 'absolute', }, chevronUp: { width: 0, height: 0, backgroundColor: 'transparent', borderStyle: 'solid', borderLeftWidth: 4, borderRightWidth: 4, borderTopWidth: 0, borderBottomWidth: 5, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderTopColor: 'transparent', position: 'absolute', top: 3, left: 8, }, chevronDown: { width: 0, height: 0, backgroundColor: 'transparent', borderStyle: 'solid', borderLeftWidth: 4, borderRightWidth: 4, borderBottomWidth: 0, borderTopWidth: 5, borderLeftColor: 'transparent', borderRightColor: 'transparent', borderBottomColor: 'transparent', position: 'absolute', top: 13, left: 8, }, }); //# sourceMappingURL=NavigationControls.js.map