npm package: @route-optimization/vanilla
Description: Vanilla JavaScript library for route optimization and map visualization
Latest version: 1.0.4

# @route-optimization/vanilla

Vanilla JavaScript library for route optimization and map visualization. No framework dependencies, works with plain JavaScript/TypeScript.

## Features

- 🎯 **Zero Dependencies** - Pure JavaScript wrapper over Google Maps
- 📦 **Tiny Bundle** - ~6KB (ESM), ~7KB (CJS)
- 🔧 **Easy Integration** - Simple API for any web project
- 🎨 **Customizable** - Full control over map appearance and behavior
- 📊 **Built-in Utilities** - Route statistics and HTML generation
- 💪 **TypeScript Support** - Full type definitions included

## Installation

```bash
npm install @route-optimization/vanilla
# or
pnpm add @route-optimization/vanilla
# or
yarn add @route-optimization/vanilla
```

## Quick Start

### HTML Setup

```html
<!DOCTYPE html>
<html>
  <head>
    <title>Route Map Example</title>
    <style>
      #map {
        width: 100%;
        height: 600px;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script type="module" src="./app.js"></script>
  </body>
</html>
```

### JavaScript

```javascript
import { RouteMap } from '@route-optimization/vanilla';

// Initialize the map
const routeMap = new RouteMap({
  apiKey: 'YOUR_GOOGLE_MAPS_API_KEY',
  container: 'map',
  center: { lat: 13.7563, lng: 100.5018 },
  zoom: 12,
  onMapReady: () => console.log('Map ready!'),
  onError: (error) => console.error('Map error:', error),
});

// Wait for initialization
await routeMap.initialize();

// Define your route
const route = {
  id: 'route-1',
  vehicleId: 'vehicle-1',
  metadata: {
    startTime: new Date().toISOString(),
    startLocation: { lat: 13.7563, lng: 100.5018 },
  },
  stops: [
    {
      id: 'depot',
      location: { lat: 13.7563, lng: 100.5018 },
      type: 'START',
      sequence: 0,
    },
    {
      id: 'delivery-1',
      location: { lat: 13.7467, lng: 100.5342 },
      type: 'DELIVERY',
      label: 'Customer #1',
      sequence: 1,
    },
    {
      id: 'depot-return',
      location: { lat: 13.7563, lng: 100.5018 },
      type: 'END',
      sequence: 2,
    },
  ],
  totalDistance: 10000,
  totalDuration: 1800,
};

// Render the route
routeMap.renderRoute(route);
```

## API Reference

### RouteMap

Main class for managing the map and routes.

#### Constructor

```typescript
new RouteMap(config: RouteMapConfig)
```

**RouteMapConfig:**

| Property   | Type                   | Required | Description                      |
| ---------- | ---------------------- | -------- | -------------------------------- |
| apiKey     | string                 | Yes      | Google Maps API key              |
| container  | string \| HTMLElement  | Yes      | Map container element or ID      |
| center     | LatLng                 | No       | Initial map center               |
| zoom       | number                 | No       | Initial zoom level (default: 12) |
| mapTypeId  | string                 | No       | Map type (default: 'roadmap')    |
| onMapReady | () => void             | No       | Callback when map is ready       |
| onError    | (error: Error) => void | No       | Error callback                   |

#### Methods

##### initialize()

Initialize the map instance.

```typescript
await routeMap.initialize(): Promise<void>
```

##### renderRoute()

Render a route on the map.

```typescript
routeMap.renderRoute(route: Route, options?: RouteRenderOptions): void
```

**Options:**

- `color?: string` - Route color (default: '#4285F4')
- `polyline?: object` - Polyline configuration

##### clearRoutes()

Clear all routes from the map.

```typescript
routeMap.clearRoutes(): void
```

##### addMarker()

Add a single marker to the map.

```typescript
routeMap.addMarker(stop: Stop, config?: MarkerConfig): void
```

##### removeMarker()

Remove a specific marker.

```typescript
routeMap.removeMarker(stopId: string): void
```

##### clearMarkers()

Remove all markers from the map.

```typescript
routeMap.clearMarkers(): void
```

##### fitBounds()

Fit map to show all markers/routes.

```typescript
routeMap.fitBounds(bounds?: MapBounds): void
```

##### setCenter()

Set map center.

```typescript
routeMap.setCenter(center: LatLng): void
```

##### setZoom()

Set map zoom level.

```typescript
routeMap.setZoom(zoom: number): void
```

##### getCenter()

Get current map center.

```typescript
routeMap.getCenter(): LatLng | null
```

##### getZoom()

Get current zoom level.

```typescript
routeMap.getZoom(): number | null
```

##### getBounds()

Get current map bounds.

```typescript
routeMap.getBounds(): MapBounds | null
```

##### getCurrentRoute()

Get the currently displayed route.

```typescript
routeMap.getCurrentRoute(): Route | null
```

##### isReady()

Check if map is initialized.

```typescript
routeMap.isReady(): boolean
```

##### destroy()

Destroy the map and clean up resources.

```typescript
routeMap.destroy(): void
```

### MapRenderer

Utility class for rendering customization and statistics.

#### Constructor

```typescript
new MapRenderer(config?: MapRendererConfig)
```

**MapRendererConfig:**

| Property       | Type                           | Default   | Description              |
| -------------- | ------------------------------ | --------- | ------------------------ |
| color          | string                         | '#4285F4' | Default route color      |
| strokeWeight   | number                         | 4         | Polyline stroke weight   |
| strokeOpacity  | number                         | 0.8       | Polyline opacity         |
| markerSize     | 'small' \| 'medium' \| 'large' | 'medium'  | Marker size              |
| showSequence   | boolean                        | true      | Show sequence numbers    |
| animateMarkers | boolean                        | false     | Animate marker placement |

#### Methods

##### generateMarkerConfig()

Generate marker configuration for a stop.

```typescript
renderer.generateMarkerConfig(stop: Stop, index: number): MarkerConfig
```

##### generatePolylineOptions()

Generate polyline rendering options.

```typescript
renderer.generatePolylineOptions(): RouteRenderOptions['polyline']
```

##### generateRenderOptions()

Generate complete rendering options.

```typescript
renderer.generateRenderOptions(): RouteRenderOptions
```

##### calculateRouteStats()

Calculate route statistics.

```typescript
renderer.calculateRouteStats(route: Route): {
  totalDistance: number;
  totalDuration: number;
  stopCount: number;
  segmentCount: number;
}
```

##### generateRouteSummary()

Generate route summary HTML.

```typescript
renderer.generateRouteSummary(route: Route): string
```

##### generateMarkerList()

Generate HTML list of markers.

```typescript
renderer.generateMarkerList(stops: Stop[]): string
```

##### updateConfig()

Update renderer configuration.

```typescript
renderer.updateConfig(config: Partial<MapRendererConfig>): void
```

##### getConfig()

Get current configuration.

```typescript
renderer.getConfig(): MapRendererConfig
```

## Advanced Usage

### Custom Rendering

```javascript
import { RouteMap, MapRenderer } from '@route-optimization/vanilla';

// Create custom renderer
const renderer = new MapRenderer({
  color: '#FF0000',
  strokeWeight: 6,
  showSequence: false,
});

// Initialize map
const routeMap = new RouteMap({
  apiKey: 'YOUR_API_KEY',
  container: 'map',
});

await routeMap.initialize();

// Render with custom options
const options = renderer.generateRenderOptions();
routeMap.renderRoute(route, options);
```

### Route Statistics Display

```javascript
const renderer = new MapRenderer();
const stats = renderer.calculateRouteStats(route);

// Display in your UI
document.getElementById('stats').innerHTML = `
  <p>Distance: ${(stats.totalDistance / 1000).toFixed(2)} km</p>
  <p>Duration: ${Math.round(stats.totalDuration / 60)} min</p>
  <p>Stops: ${stats.stopCount}</p>
`;

// Or use built-in HTML generator
document.getElementById('summary').innerHTML = renderer.generateRouteSummary(route);
```

### Dynamic Marker Management

```javascript
// Add individual markers
route.stops.forEach((stop, index) => {
  const config = renderer.generateMarkerConfig(stop, index);
  routeMap.addMarker(stop, config);
});

// Remove specific marker
routeMap.removeMarker('delivery-1');

// Clear all
routeMap.clearMarkers();
```

### Event Handling

```javascript
const routeMap = new RouteMap({
  apiKey: 'YOUR_API_KEY',
  container: 'map',
  onMapReady: () => {
    console.log('Map is ready!');
    // Auto-fit to route bounds
    routeMap.fitBounds();
  },
  onError: (error) => {
    console.error('Map error:', error);
    // Show error UI
    document.getElementById('error').textContent = error.message;
  },
});
```

### TypeScript Usage

```typescript
import { RouteMap, MapRenderer, Route, Stop } from '@route-optimization/vanilla';

const route: Route = {
  id: 'route-1',
  vehicleId: 'vehicle-1',
  metadata: {
    startTime: new Date().toISOString(),
  },
  stops: [
    {
      id: 'stop-1',
      location: { lat: 13.7563, lng: 100.5018 },
      type: 'START',
      sequence: 0,
    } as Stop,
  ],
  totalDistance: 5000,
  totalDuration: 900,
};

const routeMap = new RouteMap({
  apiKey: process.env.GOOGLE_MAPS_API_KEY!,
  container: 'map',
});
```

## Browser Support

- Chrome/Edge: Latest 2 versions
- Firefox: Latest 2 versions
- Safari: Latest 2 versions

## Bundle Size

- **ESM:** 5.84 KB
- **CJS:** 6.88 KB
- **Types:** 3.69 KB

## License

MIT

## Related Packages

- [@route-optimization/core](../core) - Core types and adapters
- [@route-optimization/react](../react) - React components and hooks
- [@route-optimization/vue](../vue) - Vue 3 composables and components
- [@route-optimization/converter](../converter) - DirectionsResult conversion utilities