UNPKG

expo-osm-sdk

Version:

OpenStreetMap component for React Native with Expo

266 lines 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useOSRMRouting = void 0; const react_1 = require("react"); const react_native_1 = require("react-native"); const osrm_1 = require("../utils/osrm"); /** * OSRM Routing Hook * * Provides comprehensive routing functionality with state management. * Handles route calculation via OSRM API, route display on native maps, * and error handling. * * @example * ```tsx * const routing = useOSRMRouting(); * const mapRef = useRef<OSMViewRef>(null); * * const handleCalculateRoute = async () => { * const route = await routing.calculateAndDisplayRoute( * { latitude: 40.7128, longitude: -74.0060 }, // NYC * { latitude: 34.0522, longitude: -118.2437 }, // LA * mapRef, * { profile: 'driving' } * ); * * if (route) { * console.log('Route calculated:', routing.formatRouteDistance(route)); * } * }; * ``` */ const useOSRMRouting = () => { const [state, setState] = (0, react_1.useState)({ isCalculating: false, error: null, currentRoute: null, routeDisplayed: false }); // Internal state update helper const updateState = (0, react_1.useCallback)((updates) => { setState(prev => ({ ...prev, ...updates })); }, []); /** * Calculate route using OSRM API */ const calculateRoute = (0, react_1.useCallback)(async (from, to, options = {}) => { try { updateState({ isCalculating: true, error: null }); const { profile = 'driving' } = options; // Validate profile-specific constraints if (profile === 'cycling') { console.log('🚴 Cycling routing: Using bike-friendly paths'); } else if (profile === 'walking') { console.log('🚶 Walking routing: Using pedestrian paths'); } else { console.log('🚗 Driving routing: Using vehicle roads'); } const routes = await (0, osrm_1.calculateRoute)([from, to], options); if (routes.length === 0) { throw new Error(`No ${profile} route found between the specified locations`); } const route = routes[0]; updateState({ currentRoute: route, isCalculating: false }); console.log(`✅ ${profile} route calculated successfully: ${(0, osrm_1.formatDistance)(route.distance)} in ${(0, osrm_1.formatDuration)(route.duration)}`); return route; } catch (error) { const errorMessage = error instanceof Error ? error.message : `${options.profile || 'driving'} route calculation failed`; console.error(`❌ Route calculation failed for ${options.profile || 'driving'}:`, errorMessage); updateState({ error: errorMessage, isCalculating: false, currentRoute: null }); return null; } }, [updateState]); /** * Display route on map (native and web) */ const displayRoute = (0, react_1.useCallback)(async (route, mapRef, options = {}) => { if (!mapRef.current) { throw new Error('Map reference not available'); } try { const routeOptions = { color: options.color || '#007AFF', width: options.width || 5, opacity: options.opacity || 0.8 }; // Convert coordinates for display const routeCoordinates = route.coordinates.map(coord => ({ latitude: coord.latitude, longitude: coord.longitude })); // Use platform-appropriate display method if ('displayRoute' in mapRef.current && typeof mapRef.current.displayRoute === 'function') { await mapRef.current.displayRoute(routeCoordinates, routeOptions); console.log(`✅ Route displayed successfully on ${react_native_1.Platform.OS} with ${routeCoordinates.length} coordinates`); } else { console.warn(`⚠️ displayRoute method not available on ${react_native_1.Platform.OS} platform`); } updateState({ routeDisplayed: true }); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Route display failed'; console.error(`❌ Route display failed on ${react_native_1.Platform.OS}:`, errorMessage); updateState({ error: errorMessage }); throw error; } }, [updateState]); /** * Calculate and display route in one step */ const calculateAndDisplayRoute = (0, react_1.useCallback)(async (from, to, mapRef, options = {}) => { try { // Extract route style options const { routeStyle, ...routeOptions } = options; // Calculate route const route = await calculateRoute(from, to, routeOptions); if (!route) { return null; } // Display route await displayRoute(route, mapRef, routeStyle); return route; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Route calculation and display failed'; updateState({ error: errorMessage }); return null; } }, [calculateRoute, displayRoute, updateState]); /** * Clear displayed route */ const clearRoute = (0, react_1.useCallback)(async (mapRef) => { if (!mapRef.current) { throw new Error('Map reference not available'); } try { // Use clearRoute method if available (both native and web) if ('clearRoute' in mapRef.current && typeof mapRef.current.clearRoute === 'function') { await mapRef.current.clearRoute(); console.log(`✅ Route cleared successfully on ${react_native_1.Platform.OS}`); } updateState({ routeDisplayed: false, currentRoute: null }); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Route clear failed'; console.error(`❌ Route clear failed on ${react_native_1.Platform.OS}:`, errorMessage); updateState({ error: errorMessage }); throw error; } }, [updateState]); /** * Fit route in map view */ const fitRouteInView = (0, react_1.useCallback)(async (route, mapRef, padding = 50) => { if (!mapRef.current) { throw new Error('Map reference not available'); } try { // Convert coordinates for display const routeCoordinates = route.coordinates.map(coord => ({ latitude: coord.latitude, longitude: coord.longitude })); // Use fitRouteInView method if available (both native and web) if ('fitRouteInView' in mapRef.current && typeof mapRef.current.fitRouteInView === 'function') { await mapRef.current.fitRouteInView(routeCoordinates, padding); console.log(`✅ Route fitted in view successfully on ${react_native_1.Platform.OS}`); } else { console.warn(`⚠️ fitRouteInView method not available on ${react_native_1.Platform.OS} platform`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Route fitting failed'; console.error(`❌ Route fitting failed on ${react_native_1.Platform.OS}:`, errorMessage); updateState({ error: errorMessage }); throw error; } }, [updateState]); /** * Format route duration in human-readable format */ const formatRouteDuration = (0, react_1.useCallback)((route) => { return (0, osrm_1.formatDuration)(route.duration); }, []); /** * Format route distance in human-readable format */ const formatRouteDistance = (0, react_1.useCallback)((route) => { return (0, osrm_1.formatDistance)(route.distance); }, []); /** * Get comprehensive route estimate with profile-specific information */ const getRouteEstimate = (0, react_1.useCallback)((route, profile = 'driving') => { const duration = (0, osrm_1.formatDuration)(route.duration); const distance = (0, osrm_1.formatDistance)(route.distance); // Calculate estimated arrival time const now = new Date(); const arrivalTime = new Date(now.getTime() + route.duration * 1000); const estimatedTime = arrivalTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); // Add profile-specific guidance let profileNote = ''; switch (profile) { case 'cycling': profileNote = 'Route optimized for bicycles'; break; case 'walking': profileNote = 'Pedestrian-friendly route'; break; case 'driving': profileNote = 'Driving route via roads'; break; } return { duration, distance, estimatedTime, profile, profileNote }; }, []); /** * Reset hook state */ const reset = (0, react_1.useCallback)(() => { setState({ isCalculating: false, error: null, currentRoute: null, routeDisplayed: false }); }, []); return { state, calculateRoute, calculateAndDisplayRoute, displayRoute, clearRoute, fitRouteInView, formatRouteDuration, formatRouteDistance, getRouteEstimate, reset }; }; exports.useOSRMRouting = useOSRMRouting; //# sourceMappingURL=useOSRMRouting.js.map