@route-optimization/vue
v1.0.4
Published
Vue 3 composables and components for route optimization and delivery management
Downloads
379
Maintainers
Readme
@route-optimization/vue
Vue 3 composables and components for route optimization and delivery management with Google Maps integration.
Installation
npm install @route-optimization/vue @route-optimization/core
# or
pnpm add @route-optimization/vue @route-optimization/core
# or
yarn add @route-optimization/vue @route-optimization/coreFeatures
- ✅ Vue 3 Composition API composables
- ✅ Ready-to-use components with slots for customization
- ✅ TypeScript support with full type definitions
- ✅ Reactive map controls (zoom, center, bounds)
- ✅ Route rendering with automatic bounds fitting
- ✅ Loading and error states built-in
- ✅ Lightweight bundle (~7KB ES, ~5KB CJS)
- ✅ Zero runtime dependencies (except Vue 3 and core)
Quick Start
Basic Usage with Component
<template>
<div>
<RouteMapView
:api-key="googleMapsApiKey"
:route="deliveryRoute"
height="500px"
:auto-fit-bounds="true"
@map-ready="onMapReady"
@route-rendered="onRouteRendered"
@error="onError"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { RouteMapView } from '@route-optimization/vue';
import type { Route } from '@route-optimization/core';
const googleMapsApiKey = 'YOUR_GOOGLE_MAPS_API_KEY';
const deliveryRoute = ref<Route>({
id: 'route-1',
vehicleId: 'vehicle-1',
stops: [
{
id: 'stop-1',
location: { lat: 13.7563, lng: 100.5018 },
address: 'Bangkok, Thailand',
type: 'START',
sequence: 0,
},
{
id: 'stop-2',
location: { lat: 13.7467, lng: 100.5342 },
address: 'Sukhumvit, Bangkok',
type: 'DELIVERY',
sequence: 1,
},
],
totalDistance: 5200,
totalDuration: 15,
status: 'pending',
});
const onMapReady = (map: google.maps.Map) => {
console.log('Map ready:', map);
};
const onRouteRendered = (route: Route) => {
console.log('Route rendered:', route);
};
const onError = (error: Error) => {
console.error('Map error:', error);
};
</script>Using Composables
<template>
<div>
<div ref="mapContainer" style="height: 500px"></div>
<div v-if="isLoading">Loading map...</div>
<div v-if="error">Error: {{ error.message }}</div>
<button @click="renderCurrentRoute" :disabled="!mapInstance">Render Route</button>
<button @click="clearRoute">Clear</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useRouteMap } from '@route-optimization/vue';
import type { Route } from '@route-optimization/core';
const mapContainer = ref<HTMLElement | null>(null);
const { mapInstance, isLoading, error, renderRoute, clearRoute, fitBounds } = useRouteMap({
apiKey: 'YOUR_GOOGLE_MAPS_API_KEY',
mapContainer,
center: { lat: 13.7563, lng: 100.5018 },
zoom: 12,
onMapReady: (map) => {
console.log('Map initialized:', map);
},
onError: (err) => {
console.error('Map error:', err);
},
});
const route = ref<Route>({
// ... your route data
});
const renderCurrentRoute = async () => {
if (route.value) {
await renderRoute(route.value);
fitBounds();
}
};
</script>Map Controls
<template>
<div style="position: relative">
<RouteMapView ref="mapViewRef" :api-key="apiKey" :route="route" height="600px" />
<MapControls
v-if="mapViewRef?.mapInstance"
:map-instance="mapViewRef.mapInstance"
:show-zoom-level="true"
:show-reset-button="true"
@zoom-change="onZoomChange"
>
<template #zoom-in-icon>
<PlusIcon />
</template>
<template #zoom-out-icon>
<MinusIcon />
</template>
</MapControls>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { RouteMapView, MapControls } from '@route-optimization/vue';
const mapViewRef = ref();
const apiKey = 'YOUR_GOOGLE_MAPS_API_KEY';
const onZoomChange = (zoom: number) => {
console.log('Zoom level:', zoom);
};
</script>API Reference
RouteMapView Component
A complete map view component with route rendering.
Props:
| Prop | Type | Default | Description |
| --------------- | --------------- | --------------------------------- | ---------------------------------- |
| apiKey | string | required | Google Maps API key |
| route | Route \| null | null | Route to display on the map |
| center | LatLng | { lat: 13.7563, lng: 100.5018 } | Initial map center |
| zoom | number | 12 | Initial zoom level |
| height | string | '500px' | Map container height |
| width | string | '100%' | Map container width |
| autoFitBounds | boolean | true | Auto-fit bounds when route changes |
Events:
| Event | Payload | Description |
| ---------------- | ----------------- | ------------------------------- |
| map-ready | google.maps.Map | Emitted when map is initialized |
| route-rendered | Route | Emitted when route is rendered |
| error | Error | Emitted when an error occurs |
Slots:
| Slot | Description |
| --------- | -------------------------------------------- |
| loading | Custom loading indicator |
| error | Custom error display (receives error prop) |
Exposed Methods:
mapInstance: Ref to Google Maps instancerenderRoute(route): Manually render a routeclearRoute(): Clear current routefitBounds(): Fit map to route bounds
MapControls Component
Customizable map zoom controls.
Props:
| Prop | Type | Default | Description |
| ----------------- | ------------------------------ | -------- | ----------------------- |
| mapInstance | Ref<google.maps.Map \| null> | required | Map instance reference |
| initialZoom | number | 12 | Initial zoom level |
| minZoom | number | 1 | Minimum zoom level |
| maxZoom | number | 20 | Maximum zoom level |
| showZoomLevel | boolean | false | Show current zoom level |
| showResetButton | boolean | false | Show reset zoom button |
Events:
| Event | Payload | Description |
| ------------- | -------- | ----------------------------- |
| zoom-change | number | Emitted when zoom changes |
| zoom-in | - | Emitted when zoom in clicked |
| zoom-out | - | Emitted when zoom out clicked |
| reset | - | Emitted when reset clicked |
Slots:
| Slot | Description |
| ----------------- | ------------------------------ |
| before-controls | Content before zoom controls |
| after-controls | Content after zoom controls |
| zoom-in-icon | Custom zoom in button content |
| zoom-out-icon | Custom zoom out button content |
| reset-icon | Custom reset button content |
useRouteMap Composable
Composable for managing map instance and route rendering.
function useRouteMap(options: UseRouteMapOptions): UseRouteMapReturn;
interface UseRouteMapOptions {
apiKey: string;
mapContainer: Ref<HTMLElement | null>;
center?: LatLng;
zoom?: number;
onMapReady?: (map: google.maps.Map) => void;
onError?: (error: Error) => void;
}
interface UseRouteMapReturn {
mapInstance: Ref<google.maps.Map | null>;
isLoading: Ref<boolean>;
error: Ref<Error | null>;
renderRoute: (route: Route) => Promise<void>;
clearRoute: () => void;
fitBounds: () => void;
}useMapControls Composable
Composable for managing map zoom controls.
function useMapControls(
mapInstance: Ref<google.maps.Map | null>,
options?: UseMapControlsOptions
): UseMapControlsReturn;
interface UseMapControlsOptions {
initialZoom?: number;
minZoom?: number;
maxZoom?: number;
onZoomChange?: (zoom: number) => void;
}
interface UseMapControlsReturn {
zoom: Ref<number>;
canZoomIn: Ref<boolean>;
canZoomOut: Ref<boolean>;
zoomIn: () => void;
zoomOut: () => void;
setZoom: (level: number) => void;
resetZoom: () => void;
}Advanced Usage
Custom Loading State
<RouteMapView :api-key="apiKey" :route="route">
<template #loading>
<div class="custom-loader">
<SpinnerIcon />
<p>Initializing map...</p>
</div>
</template>
</RouteMapView>Custom Error Handling
<RouteMapView :api-key="apiKey" :route="route">
<template #error="{ error }">
<div class="error-card">
<ErrorIcon />
<h3>Map Error</h3>
<p>{{ error.message }}</p>
<button @click="retry">Retry</button>
</div>
</template>
</RouteMapView>Dynamic Route Updates
<script setup lang="ts">
import { ref, watch } from 'vue';
import { RouteMapView } from '@route-optimization/vue';
const currentRoute = ref<Route | null>(null);
// Watch for route changes from your state management
watch(
() => store.optimizedRoute,
(newRoute) => {
currentRoute.value = newRoute;
}
);
</script>
<template>
<RouteMapView :api-key="apiKey" :route="currentRoute" :auto-fit-bounds="true" />
</template>Type Definitions
This package re-exports all types from @route-optimization/core:
import type { Route, Stop, Vehicle, LatLng, RouteMetrics, StopType } from '@route-optimization/vue';Bundle Size
- ES Module: ~7.0 KB (2.3 KB gzipped)
- CommonJS: ~5.1 KB (1.9 KB gzipped)
- Includes CSS: ~1.6 KB (0.6 KB gzipped)
Browser Support
- Modern browsers with ES2020 support
- Vue 3.3.0 or higher required
- Google Maps JavaScript API v3
Related Packages
- @route-optimization/core - Core types and utilities
- @route-optimization/react - React hooks and components
- @route-optimization/converter - DirectionsResult format conversion
License
MIT
Contributing
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
