@madebylars.com/mbl-fleetmap 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +301 -0
- package/dist/module.d.mts +18 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +32 -0
- package/dist/runtime/components/MblFleetMap.d.vue.ts +20 -0
- package/dist/runtime/components/MblFleetMap.vue +41 -0
- package/dist/runtime/components/MblFleetMap.vue.d.ts +20 -0
- package/dist/runtime/composables/useDriverMarkers.d.ts +22 -0
- package/dist/runtime/composables/useDriverMarkers.js +72 -0
- package/dist/runtime/composables/useFleetMap.d.ts +7 -0
- package/dist/runtime/composables/useFleetMap.js +16 -0
- package/dist/runtime/composables/useFleetRoute.d.ts +772 -0
- package/dist/runtime/composables/useFleetRoute.js +28 -0
- package/dist/runtime/composables/useJobPins.d.ts +6 -0
- package/dist/runtime/composables/useJobPins.js +62 -0
- package/dist/runtime/composables/useMapEvents.d.ts +7 -0
- package/dist/runtime/composables/useMapEvents.js +19 -0
- package/dist/runtime/plugin.d.ts +2 -0
- package/dist/runtime/plugin.js +7 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/utils/events.d.ts +19 -0
- package/dist/runtime/utils/events.js +24 -0
- package/dist/runtime/utils/registry.d.ts +6 -0
- package/dist/runtime/utils/registry.js +10 -0
- package/dist/types.d.mts +3 -0
- package/package.json +65 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import { getMap, getLeaflet } from "../utils/registry.js";
|
|
3
|
+
export function useFleetRoute(mapId) {
|
|
4
|
+
const routes = ref(/* @__PURE__ */ new Map());
|
|
5
|
+
const drawRoute = (jobId, waypoints) => {
|
|
6
|
+
const L = getLeaflet();
|
|
7
|
+
const map = getMap(mapId);
|
|
8
|
+
if (!L || !map) return;
|
|
9
|
+
clearRoute(jobId);
|
|
10
|
+
const polyline = L.polyline(waypoints, {
|
|
11
|
+
color: "#2563eb",
|
|
12
|
+
weight: 4,
|
|
13
|
+
opacity: 0.8
|
|
14
|
+
}).addTo(map);
|
|
15
|
+
routes.value.set(jobId, polyline);
|
|
16
|
+
};
|
|
17
|
+
const clearRoute = (jobId) => {
|
|
18
|
+
const route = routes.value.get(jobId);
|
|
19
|
+
if (!route) return;
|
|
20
|
+
route.remove();
|
|
21
|
+
routes.value.delete(jobId);
|
|
22
|
+
};
|
|
23
|
+
const clearAll = () => {
|
|
24
|
+
routes.value.forEach((route) => route.remove());
|
|
25
|
+
routes.value.clear();
|
|
26
|
+
};
|
|
27
|
+
return { drawRoute, clearRoute, clearAll, routes };
|
|
28
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function useJobPins(mapId: string): {
|
|
2
|
+
setPickup: (jobId: string, lat: number, lng: number, label?: string) => void;
|
|
3
|
+
setDropoff: (jobId: string, lat: number, lng: number, label?: string) => void;
|
|
4
|
+
clearJob: (jobId: string) => void;
|
|
5
|
+
clearAll: () => void;
|
|
6
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getMap, getLeaflet } from "../utils/registry.js";
|
|
2
|
+
const PIN_COLORS = {
|
|
3
|
+
pickup: "#16a34a",
|
|
4
|
+
dropoff: "#dc2626"
|
|
5
|
+
};
|
|
6
|
+
function createPinIcon(L, type) {
|
|
7
|
+
const color = PIN_COLORS[type];
|
|
8
|
+
return L.divIcon({
|
|
9
|
+
className: "",
|
|
10
|
+
html: `<div style="position:relative;width:24px;height:36px;">
|
|
11
|
+
<div style="
|
|
12
|
+
position:absolute;top:0;left:0;
|
|
13
|
+
width:24px;height:24px;
|
|
14
|
+
border-radius:50% 50% 50% 0;
|
|
15
|
+
background:${color};
|
|
16
|
+
transform:rotate(-45deg);
|
|
17
|
+
box-shadow:0 2px 4px rgba(0,0,0,.3);
|
|
18
|
+
"></div>
|
|
19
|
+
<div style="
|
|
20
|
+
position:absolute;top:4px;left:4px;
|
|
21
|
+
width:16px;height:16px;
|
|
22
|
+
border-radius:50%;
|
|
23
|
+
background:#fff;
|
|
24
|
+
"></div>
|
|
25
|
+
</div>`,
|
|
26
|
+
iconSize: [24, 36],
|
|
27
|
+
iconAnchor: [12, 36],
|
|
28
|
+
tooltipAnchor: [12, -36]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function useJobPins(mapId) {
|
|
32
|
+
const pinInstances = /* @__PURE__ */ new Map();
|
|
33
|
+
function upsertPin(type, jobId, lat, lng, label) {
|
|
34
|
+
const L = getLeaflet();
|
|
35
|
+
const map = getMap(mapId);
|
|
36
|
+
if (!L || !map) return;
|
|
37
|
+
const pair = pinInstances.get(jobId) ?? {};
|
|
38
|
+
pair[type]?.remove();
|
|
39
|
+
const marker = L.marker([lat, lng], { icon: createPinIcon(L, type) }).addTo(map);
|
|
40
|
+
const tooltipText = label ?? (type === "pickup" ? "Pickup" : "Dropoff");
|
|
41
|
+
marker.bindTooltip(tooltipText, { permanent: false, direction: "top" });
|
|
42
|
+
pair[type] = marker;
|
|
43
|
+
pinInstances.set(jobId, pair);
|
|
44
|
+
}
|
|
45
|
+
const setPickup = (jobId, lat, lng, label) => upsertPin("pickup", jobId, lat, lng, label);
|
|
46
|
+
const setDropoff = (jobId, lat, lng, label) => upsertPin("dropoff", jobId, lat, lng, label);
|
|
47
|
+
const clearJob = (jobId) => {
|
|
48
|
+
const pair = pinInstances.get(jobId);
|
|
49
|
+
if (!pair) return;
|
|
50
|
+
pair.pickup?.remove();
|
|
51
|
+
pair.dropoff?.remove();
|
|
52
|
+
pinInstances.delete(jobId);
|
|
53
|
+
};
|
|
54
|
+
const clearAll = () => {
|
|
55
|
+
pinInstances.forEach((pair) => {
|
|
56
|
+
pair.pickup?.remove();
|
|
57
|
+
pair.dropoff?.remove();
|
|
58
|
+
});
|
|
59
|
+
pinInstances.clear();
|
|
60
|
+
};
|
|
61
|
+
return { setPickup, setDropoff, clearJob, clearAll };
|
|
62
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DriverMarker } from '../../types.js';
|
|
2
|
+
export declare function useMapEvents(mapId: string): {
|
|
3
|
+
onDriverClick: (handler: (driver: DriverMarker) => void) => void;
|
|
4
|
+
onMapClick: (handler: (lat: number, lng: number) => void) => void;
|
|
5
|
+
onDriverHover: (handler: (driver: DriverMarker | null) => void) => void;
|
|
6
|
+
offAll: () => void;
|
|
7
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addDriverClickHandler,
|
|
3
|
+
addMapClickHandler,
|
|
4
|
+
addDriverHoverHandler,
|
|
5
|
+
clearBus
|
|
6
|
+
} from "../utils/events.js";
|
|
7
|
+
export function useMapEvents(mapId) {
|
|
8
|
+
const onDriverClick = (handler) => {
|
|
9
|
+
addDriverClickHandler(mapId, handler);
|
|
10
|
+
};
|
|
11
|
+
const onMapClick = (handler) => {
|
|
12
|
+
addMapClickHandler(mapId, ({ lat, lng }) => handler(lat, lng));
|
|
13
|
+
};
|
|
14
|
+
const onDriverHover = (handler) => {
|
|
15
|
+
addDriverHoverHandler(mapId, handler);
|
|
16
|
+
};
|
|
17
|
+
const offAll = () => clearBus(mapId);
|
|
18
|
+
return { onDriverClick, onMapClick, onDriverHover, offAll };
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DriverMarker } from '../../types.js';
|
|
2
|
+
type Handler<T> = (payload: T) => void;
|
|
3
|
+
export declare const emitDriverClick: (mapId: string, driver: DriverMarker) => void;
|
|
4
|
+
export declare const emitMapClick: (mapId: string, payload: {
|
|
5
|
+
lat: number;
|
|
6
|
+
lng: number;
|
|
7
|
+
}) => void;
|
|
8
|
+
export declare const emitDriverHover: (mapId: string, driver: DriverMarker | null) => void;
|
|
9
|
+
export declare const addDriverClickHandler: (mapId: string, handler: Handler<DriverMarker>) => Set<Handler<DriverMarker>>;
|
|
10
|
+
export declare const addMapClickHandler: (mapId: string, handler: Handler<{
|
|
11
|
+
lat: number;
|
|
12
|
+
lng: number;
|
|
13
|
+
}>) => Set<Handler<{
|
|
14
|
+
lat: number;
|
|
15
|
+
lng: number;
|
|
16
|
+
}>>;
|
|
17
|
+
export declare const addDriverHoverHandler: (mapId: string, handler: Handler<DriverMarker | null>) => Set<Handler<DriverMarker | null>>;
|
|
18
|
+
export declare const clearBus: (mapId: string) => void;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const busRegistry = /* @__PURE__ */ new Map();
|
|
2
|
+
function getBus(mapId) {
|
|
3
|
+
if (!busRegistry.has(mapId)) {
|
|
4
|
+
busRegistry.set(mapId, {
|
|
5
|
+
driverClick: /* @__PURE__ */ new Set(),
|
|
6
|
+
mapClick: /* @__PURE__ */ new Set(),
|
|
7
|
+
driverHover: /* @__PURE__ */ new Set()
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
return busRegistry.get(mapId);
|
|
11
|
+
}
|
|
12
|
+
export const emitDriverClick = (mapId, driver) => getBus(mapId).driverClick.forEach((h) => h(driver));
|
|
13
|
+
export const emitMapClick = (mapId, payload) => getBus(mapId).mapClick.forEach((h) => h(payload));
|
|
14
|
+
export const emitDriverHover = (mapId, driver) => getBus(mapId).driverHover.forEach((h) => h(driver));
|
|
15
|
+
export const addDriverClickHandler = (mapId, handler) => getBus(mapId).driverClick.add(handler);
|
|
16
|
+
export const addMapClickHandler = (mapId, handler) => getBus(mapId).mapClick.add(handler);
|
|
17
|
+
export const addDriverHoverHandler = (mapId, handler) => getBus(mapId).driverHover.add(handler);
|
|
18
|
+
export const clearBus = (mapId) => {
|
|
19
|
+
const bus = busRegistry.get(mapId);
|
|
20
|
+
if (!bus) return;
|
|
21
|
+
bus.driverClick.clear();
|
|
22
|
+
bus.mapClick.clear();
|
|
23
|
+
bus.driverHover.clear();
|
|
24
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type L from 'leaflet';
|
|
2
|
+
export declare const registerMap: (id: string, map: L.Map) => import("vue").ShallowReactive<Map<string, L.Map>>;
|
|
3
|
+
export declare const getMap: (id: string) => L.Map | null;
|
|
4
|
+
export declare const removeMap: (id: string) => boolean;
|
|
5
|
+
export declare const setLeaflet: (L: unknown) => void;
|
|
6
|
+
export declare const getLeaflet: () => typeof import("leaflet") | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { shallowReactive } from "vue";
|
|
2
|
+
const mapRegistry = shallowReactive(/* @__PURE__ */ new Map());
|
|
3
|
+
export const registerMap = (id, map) => mapRegistry.set(id, map);
|
|
4
|
+
export const getMap = (id) => mapRegistry.get(id) ?? null;
|
|
5
|
+
export const removeMap = (id) => mapRegistry.delete(id);
|
|
6
|
+
let _leaflet = null;
|
|
7
|
+
export const setLeaflet = (L) => {
|
|
8
|
+
_leaflet = L;
|
|
9
|
+
};
|
|
10
|
+
export const getLeaflet = () => _leaflet;
|
package/dist/types.d.mts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@madebylars.com/mbl-fleetmap",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Nuxt 4 module — Leaflet-powered transport map with driver markers and route API",
|
|
5
|
+
"repository": "madebylars/mbl-fleetmap",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types.d.mts",
|
|
11
|
+
"import": "./dist/module.mjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/module.mjs",
|
|
15
|
+
"typesVersions": {
|
|
16
|
+
"*": {
|
|
17
|
+
".": [
|
|
18
|
+
"./dist/types.d.mts"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"workspaces": [
|
|
26
|
+
"playground"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"prepack": "nuxt-module-build build",
|
|
30
|
+
"dev": "npm run dev:prepare && nuxt dev playground",
|
|
31
|
+
"dev:build": "nuxt build playground",
|
|
32
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
|
|
33
|
+
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
34
|
+
"lint": "eslint .",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest watch",
|
|
37
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@nuxt/kit": "^4.4.7",
|
|
41
|
+
"@vue-leaflet/vue-leaflet": "^0.10.1",
|
|
42
|
+
"leaflet": "^1.9.4"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@nuxt/devtools": "^3.2.4",
|
|
46
|
+
"@nuxt/eslint-config": "^1.15.2",
|
|
47
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
48
|
+
"@nuxt/schema": "^4.4.7",
|
|
49
|
+
"@nuxt/test-utils": "^4.0.3",
|
|
50
|
+
"@types/leaflet": "^1.9.21",
|
|
51
|
+
"@types/node": "latest",
|
|
52
|
+
"changelogen": "^0.6.2",
|
|
53
|
+
"eslint": "^10.4.1",
|
|
54
|
+
"nuxt": "^4.4.7",
|
|
55
|
+
"typescript": "~6.0.3",
|
|
56
|
+
"vitest": "^4.1.8",
|
|
57
|
+
"vue-tsc": "^3.3.3"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"nuxt": "^4.0.0"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
}
|
|
65
|
+
}
|