expo-osm-sdk
Version:
OpenStreetMap component for React Native with Expo
266 lines • 10.1 kB
JavaScript
;
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