npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

wakeb-map

v2.1.7

Published

A free Vue 3 multi-provider map library (Leaflet + Mapbox GL JS + extensible) with location picking, markers, geocoding, drawing, tracking, and more. No API key required for Leaflet. Works offline!

Downloads

1,170

Readme

wakeb-map

A free, multi-provider Vue 3 map library supporting Leaflet, Mapbox GL JS, Google Maps, and custom providers.
Default engine: Leaflet + OpenStreetMap — zero API key needed.
Includes a built-in SVG vector map engine (world maps, regions, markers, lines — no external dependencies).
Full offline support, 19 composables, 3 components, and 30+ utility functions.

npm license


Features

Components

| Component | Description | | ------------------ | ------------------------------------------------------------------------------------------------ | | <WakebMap> | Multi-provider map — markers, polylines, circles, polygons, drawing, fullscreen, layer switching | | <WakebMapPicker> | Ready-made location picker — search, pin, confirm, address display | | <WakebVectorMap> | Pure SVG vector map — world regions, data visualization, series, tooltips (zero deps) |

Composables (19)

| Category | Composables | | ----------------- | -------------------------------------------------------------------------------------- | | Core | useWakebMap · useDrawing · useGeofence · useMarkerCluster · useWakebTracking | | Fleet | useFleetTracking · useRouteFollowing | | Visualization | useChoropleth · useHeatmap · useTimeSlider | | Routing | useRouting · useGeocoder · useElevation | | Overlays | useImageOverlay · useWMS · useLiveData | | UI | useMapScreenshot · useMinimap | | Vector | useVectorMap |

Key Highlights

  • 100% Free — no API key, no subscription, no usage limits (Leaflet default)
  • Multi-Provider — switch between Leaflet, Mapbox GL JS, or Google Maps per-component with one prop
  • Works Offline — built-in canvas tile layer, inline SVG markers, Haversine distance — all work without internet
  • Vector Map Engine — pure SVG renderer with regions, markers, curved/straight lines, animated dash flow, fade-in animations, data series, tooltips, zoom/pan, touch support
  • 5 Map Styles — streets, satellite, topo, dark, offline (auto-mapped across providers)
  • Free Geocoding — Nominatim address search + reverse geocode
  • Drawing — paths, polygons, rectangles, circles, measurements, with constraint boundaries
  • Fleet Tracking — real-time vehicle/entity tracking with animated movement
  • Full TypeScript — every type exported

Installation

npm install wakeb-map

vue (>=3.3) and leaflet (>=1.9.4) are peer dependencies:

npm install wakeb-map leaflet
npm install -D @types/leaflet

Optional: Mapbox GL JS

npm install mapbox-gl

Then register the provider:

import mapboxgl from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";
import { createMapboxProvider, registerProvider } from "wakeb-map";

registerProvider(createMapboxProvider(mapboxgl));

Optional: Google Maps

npm install @googlemaps/js-api-loader

Then register the provider:

import { Loader } from "@googlemaps/js-api-loader";
import { createGoogleMapsProvider, registerProvider } from "wakeb-map";

const google = await new Loader({ apiKey: "YOUR_KEY" }).load();
registerProvider(createGoogleMapsProvider(google));

Quick Start

Basic Map

<template>
  <WakebMap
    :center="{ lat: 24.7136, lng: 46.6753 }"
    :zoom="14"
    :markers="markers"
    height="500px"
    @click="onMapClick"
    @marker-click="onMarkerClick"
  />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { WakebMap } from "wakeb-map";
import "wakeb-map/style.css";
import type { WakebLatLng, WakebMarker } from "wakeb-map";

const markers = ref<WakebMarker[]>([
  {
    id: "1",
    position: { lat: 24.7136, lng: 46.6753 },
    title: "Riyadh",
    snippet: "Capital of Saudi Arabia",
  },
]);

function onMapClick(e: { position: WakebLatLng }) {
  console.log("Clicked:", e.position.lat, e.position.lng);
}

function onMarkerClick(marker: WakebMarker) {
  console.log("Marker:", marker.title);
}
</script>

Location Picker

<template>
  <WakebMapPicker
    v-model="location"
    height="500px"
    confirm-label="Confirm Location"
    @location-picked="onPicked"
  />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { WakebMapPicker } from "wakeb-map";
import "wakeb-map/style.css";
import type { WakebLatLng } from "wakeb-map";

const location = ref<WakebLatLng | null>(null);

function onPicked(result: { position: WakebLatLng; address: string }) {
  console.log(result.position, result.address);
}
</script>

Vector Map (SVG — No External Dependencies)

<template>
  <div ref="mapEl" style="width: 100%; height: 400px" />
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useVectorMap } from "wakeb-map";

const mapEl = ref<HTMLElement | null>(null);

const vectorMap = useVectorMap({
  map: "world",
  regionStyle: {
    initial: { fill: "#d1d5db", stroke: "#fff", strokeWidth: 0.5 },
    hover: { fill: "#3b82f6", fillOpacity: 0.8 },
    selected: { fill: "#10b981" },
  },
  markerStyle: {
    initial: { fill: "#ef4444", stroke: "#fff", r: 6 },
    hover: { fill: "#f59e0b", r: 8 },
  },
  lineStyle: {
    stroke: "#3b82f6",
    strokeWidth: 1.5,
    strokeDasharray: "6 3 6",
    animation: true,
    curvature: 0.15,
  },
  zoomButtons: true,
  showTooltip: true,
  regionsSelectable: true,
});

onMounted(() => {
  if (mapEl.value) vectorMap.init(mapEl.value);

  vectorMap.addMarkers([
    { name: "Cairo", coords: [30.04, 31.24] },
    { name: "London", coords: [51.51, -0.13] },
    { name: "Tokyo", coords: [35.68, 139.69] },
  ]);

  vectorMap.addLines([
    { from: "Cairo", to: "London" },
    { from: "London", to: "Tokyo" },
  ]);
});
</script>

Plugin Setup (Optional)

Register globally to set default center, zoom, map type, provider, and offline options:

import { createApp } from "vue";
import { WakebMapPlugin } from "wakeb-map";
import "wakeb-map/style.css";

const app = createApp(App);

app.use(WakebMapPlugin, {
  language: "ar",
  defaultCenter: { lat: 24.7136, lng: 46.6753 },
  defaultZoom: 14,
  defaultMapType: "streets",
  // provider: "mapbox",          // uncomment to use Mapbox as default
  // mapboxAccessToken: "pk.xxx", // required when using Mapbox
  // provider: "google",          // uncomment to use Google Maps as default
});

app.mount("#app");

Offline Mode

Full offline support — the map, markers, shapes, GPS, and distance all work without internet.

// Option 1: Plugin config
app.use(WakebMapPlugin, {
  offline: true,
  offlineGridColor: "#ddd",
  offlineBgColor: "#f0f0f0",
});

// Option 2: Component prop
// <WakebMap map-type="offline" />

// Option 3: Manual tile layer
import { createOfflineTileLayer } from "wakeb-map";
const offlineLayer = createOfflineTileLayer({ offlineGridColor: "#ccc" });

| Feature | Offline? | | -------------- | ---------------------------- | | Map rendering | ✅ Canvas coordinate grid | | Markers | ✅ Inline SVG icons (no CDN) | | Shapes | ✅ Lines, circles, polygons | | GPS | ✅ Browser hardware | | Distance | ✅ Haversine formula (local) | | Vector Map | ✅ Pure SVG (fully embedded) | | Address search | ❌ Requires internet | | Geocoding | ❌ Returns null gracefully |


Map Providers

Switching Providers

<!-- Default: Leaflet (no setup needed) -->
<WakebMap :center="center" :zoom="14" height="400px" />

<!-- Mapbox GL JS -->
<WakebMap
  provider="mapbox"
  access-token="pk.xxx"
  :center="center"
  :zoom="14"
  height="400px"
/>

<!-- Google Maps -->
<WakebMap provider="google" :center="center" :zoom="14" height="400px" />

<!-- All three on the same page -->
<WakebMap :center="center" :zoom="14" height="400px" />
<WakebMap
  provider="mapbox"
  access-token="pk.xxx"
  :center="center"
  :zoom="14"
  height="400px"
/>
<WakebMap provider="google" :center="center" :zoom="14" height="400px" />

Provider Comparison

| Feature | Leaflet | Mapbox GL JS | Google Maps | | --------------- | ------------------ | -------------------- | -------------------- | | API Key | Not needed | Required (free tier) | Required (free tier) | | Tile Rendering | Raster | Vector (WebGL) | Vector | | 3D Terrain | No | Yes | Limited | | Offline Support | Yes (canvas tiles) | No | No | | Bundle Size | ~40 KB | ~200 KB | Loaded via script |

Composable Compatibility

| Composable | Leaflet | Mapbox | Google | Notes | | ------------------- | ------- | ------ | ------ | ---------------------------------- | | useWakebMap | ✅ | ✅ | ✅ | Provider-independent (reactive) | | useWakebTracking | ✅ | ✅ | ✅ | Provider-independent | | useFleetTracking | ✅ | ✅ | ✅ | Provider-independent | | useRouteFollowing | ✅ | ✅ | ✅ | Provider-independent | | useGeofence | ✅ | ✅ | ✅ | Provider-independent | | useMarkerCluster | ✅ | ✅ | ✅ | Provider-independent | | useTimeSlider | ✅ | ✅ | ✅ | Provider-independent | | useLiveData | ✅ | ✅ | ✅ | Provider-independent | | useVectorMap | ✅ | ✅ | ✅ | Pure SVG, no map engine dependency | | useDrawing | ✅ | ❌ | ❌ | Leaflet L.Draw only | | useChoropleth | ✅ | ❌ | ❌ | Leaflet GeoJSON layers | | useHeatmap | ✅ | ❌ | ❌ | Leaflet heatmap plugin | | useElevation | ✅ | ❌ | ❌ | Leaflet elevation control | | useGeocoder | ✅ | ❌ | ❌ | Leaflet geocoder control | | useImageOverlay | ✅ | ❌ | ❌ | Leaflet image overlay | | useMapScreenshot | ✅ | ❌ | ❌ | Leaflet canvas export | | useMinimap | ✅ | ❌ | ❌ | Leaflet minimap control | | useRouting | ✅ | ❌ | ❌ | Leaflet routing machine | | useWMS | ✅ | ❌ | ❌ | Leaflet WMS layer |


Map Styles

| Style | Source | Online? | | ----------- | ------------------ | ------- | | streets | OpenStreetMap | Yes | | satellite | Esri World Imagery | Yes | | topo | OpenTopoMap | Yes | | dark | CARTO Dark | Yes | | offline | Built-in canvas | No |

<WakebMap map-type="satellite" />
<WakebMap map-type="dark" />
<WakebMap map-type="topo" />
<WakebMap map-type="offline" />

Composable Examples

useWakebMap

import { useWakebMap } from "wakeb-map";

const {
  position,
  address,
  zoom,
  markers,
  loading,
  setPosition,
  pickMyLocation,
  searchAddress,
  addMarker,
  distanceTo,
} = useWakebMap({ lat: 24.7136, lng: 46.6753 });

useDrawing

import { useDrawing } from "wakeb-map";

const drawing = useDrawing();
drawing.bindMap(leafletMap);
drawing.startDrawing("polygon", { color: "#2196F3", showMeasurements: true });
const result = drawing.finishDrawing();

useGeocoder

import { useGeocoder } from "wakeb-map";

const { search, reverse, results, loading } = useGeocoder();
await search("Kingdom Tower, Riyadh");
await reverse({ lat: 24.7136, lng: 46.6753 });

useRouting

import { useRouting } from "wakeb-map";

const { calculateRoute, route, instructions } = useRouting();
await calculateRoute(
  { lat: 24.7136, lng: 46.6753 },
  { lat: 21.4225, lng: 39.8262 },
  { profile: "driving" },
);

useHeatmap

import { useHeatmap } from "wakeb-map";

const { addPoints, setOptions } = useHeatmap(leafletMap);
addPoints([
  { lat: 24.71, lng: 46.67, intensity: 0.8 },
  { lat: 24.72, lng: 46.68, intensity: 0.5 },
]);

useFleetTracking

import { useFleetTracking } from "wakeb-map";

const fleet = useFleetTracking(leafletMap, {
  showTrails: true,
  animateMovement: true,
});
fleet.updateEntity({
  id: "truck-1",
  type: "truck",
  position: { lat: 24.7, lng: 46.6 },
});

Utilities

Geocoding (Free — Nominatim)

import { reverseGeocode, geocodeAddress } from "wakeb-map";

const addr = await reverseGeocode({ lat: 24.7136, lng: 46.6753 });
const pos = await geocodeAddress("Kingdom Tower, Riyadh");

Distance & Geometry

import {
  calculateDistance,
  calculateBearing,
  midpoint,
  isPointInPolygon,
  isPointInCircle,
  polygonArea,
  pathLength,
  getBoundingBox,
  convexHull,
  simplifyPath,
  bufferPoint,
  distanceMatrix,
} from "wakeb-map";

const meters = calculateDistance(
  { lat: 24.7136, lng: 46.6753 },
  { lat: 21.4225, lng: 39.8262 },
);

GeoJSON Import/Export

import { exportToGeoJSON, importFromGeoJSON, downloadGeoJSON } from "wakeb-map";

const geojson = exportToGeoJSON({ markers, polylines, polygons, circles });
const data = importFromGeoJSON(geojsonObject);
downloadGeoJSON(geojson, "my-map.geojson");

Props Reference

<WakebMap>

| Prop | Type | Default | Description | | --------------------- | ----------------- | -------------------------------- | ------------------------------------------------ | | center | WakebLatLng | { lat: 24.7136, lng: 46.6753 } | Map center | | zoom | number | 14 | Zoom level | | mapType | WakebMapType | 'streets' | Tile layer preset | | provider | string | 'leaflet' | Map provider ('leaflet'/'mapbox'/'google') | | accessToken | string | — | Mapbox access token | | mapStyle | string | — | Mapbox style URL | | markers | WakebMarker[] | [] | Marker array | | polylines | WakebPolyline[] | [] | Polyline array | | circles | WakebCircle[] | [] | Circle array | | polygons | WakebPolygon[] | [] | Polygon array | | routes | WakebRoute[] | [] | Route array | | width | string | '100%' | Container width | | height | string | '400px' | Container height | | clickToAddMarker | boolean | false | Click to place markers | | markerColor | string | 'red' | Default marker color | | markerDraggable | boolean | true | Click-to-add markers draggable | | animateMarkers | boolean | false | Smooth animated marker movement | | showScale | boolean | false | Scale control | | showFullscreen | boolean | false | Fullscreen button | | showLayerSwitcher | boolean | false | Layer switcher overlay | | showGeolocation | boolean | false | "My Location" button | | showCoordinates | boolean | false | Cursor coordinate display | | showDrawingToolbar | boolean | false | Drawing toolbar | | cooperativeGestures | boolean | false | Ctrl+scroll to zoom | | keyboardNavigation | boolean | false | Arrow key panning | | hashRouting | boolean | false | Sync state with URL hash | | zoomControl | boolean | true | Zoom buttons | | options | object | {} | Extra map options (provider-specific) |

<WakebMapPicker>

| Prop | Type | Default | Description | | ------------------- | -------------- | -------------------- | ----------------- | | v-model | WakebLatLng | — | Selected location | | mapType | WakebMapType | 'streets' | Map style | | showSearch | boolean | true | Search input | | showMyLocation | boolean | true | GPS button | | showAddress | boolean | true | Address display | | useCenterPin | boolean | true | Center pin mode | | showConfirmButton | boolean | true | Confirm button | | confirmLabel | string | 'Confirm Location' | Button text |


Events

<WakebMap>

| Event | Payload | Description | | ----------------- | ------------------------------------------------------- | --------------------------- | | click | { position, originalEvent } | Map click | | markerClick | WakebMarker | Marker click | | markerDragEnd | (marker, newPosition) | Marker drag end | | markerDragStart | WakebMarker | Marker drag start | | markerAdded | WakebMarker | Marker added (click-to-add) | | markerRemoved | markerId | Marker removed | | cameraChange | WakebCameraPosition | Viewport change | | mapReady | native map instance | Map initialized | | providerReady | WakebMapProviderInstance | Provider instance ready | | drawComplete | WakebDrawnPath \| WakebDrawnShape \| WakebMeasurement | Drawing finished | | drawUpdate | same | Drawing updated | | geolocation | WakebLatLng | User location acquired | | update:center | WakebLatLng | Center changed | | update:zoom | number | Zoom changed |

<WakebMapPicker>

| Event | Payload | Description | | ------------------- | ----------------------- | ------------------ | | update:modelValue | WakebLatLng | Location updated | | locationPicked | { position, address } | Location confirmed |


Documentation

Full interactive docs with live demos:

visit the hosted docs at wakeb-map.surge.sh


License

MIT © Kerolos Zakaria