import { updateGridOverlay } from "./maidenhead_grid" interface ContactMapHook extends ViewHook { gridLayer: L.LayerGroup gridVisible: boolean initMap(): void } export const ContactMap = { mounted(this: ContactMapHook) { // Defer init until container has dimensions (flex layout timing) requestAnimationFrame(() => this.initMap()) }, initMap(this: ContactMapHook) { const pos1 = JSON.parse(this.el.dataset.pos1!) as { lat: number; lon: number } const pos2 = JSON.parse(this.el.dataset.pos2!) as { lat: number; lon: number } const lat1 = pos1.lat const lon1 = pos1.lon const lat2 = pos2.lat const lon2 = pos2.lon const bounds = L.latLngBounds([[lat1, lon1], [lat2, lon2]]) const map = L.map(this.el, { zoomControl: true, attributionControl: false, scrollWheelZoom: false }).fitBounds(bounds, {padding: [40, 40], maxZoom: 10}) L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19 }).addTo(map) // Grid overlay this.gridLayer = L.layerGroup().addTo(map) this.gridVisible = true updateGridOverlay(map, this.gridLayer) map.on("moveend", () => { if (this.gridVisible) updateGridOverlay(map, this.gridLayer) }) // Grid toggle control const GridToggle = L.Control.extend({ options: { position: "topright" as const }, onAdd: () => { const btn = L.DomUtil.create("button", "leaflet-bar leaflet-control") btn.innerHTML = "Grid" btn.title = "Toggle Maidenhead grid" btn.style.cssText = "background:#fff;padding:4px 8px;font-size:12px;cursor:pointer;font-weight:600;" L.DomEvent.disableClickPropagation(btn) btn.onclick = () => { this.gridVisible = !this.gridVisible if (this.gridVisible) { this.gridLayer.addTo(map) updateGridOverlay(map, this.gridLayer) btn.style.opacity = "1" } else { this.gridLayer.remove() btn.style.opacity = "0.5" } } return btn } }) new GridToggle().addTo(map) const marker1 = L.circleMarker([lat1, lon1], { radius: 6, color: "#2563eb", fillColor: "#3b82f6", fillOpacity: 0.9, weight: 2 }).addTo(map) const marker2 = L.circleMarker([lat2, lon2], { radius: 6, color: "#dc2626", fillColor: "#ef4444", fillOpacity: 0.9, weight: 2 }).addTo(map) const station1 = this.el.dataset.station1 const station2 = this.el.dataset.station2 if (station1) marker1.bindTooltip(station1, {permanent: true, direction: "top", offset: [0, -8]}) if (station2) marker2.bindTooltip(station2, {permanent: true, direction: "top", offset: [0, -8]}) L.polyline([[lat1, lon1], [lat2, lon2]], { color: "#6366f1", weight: 2, dashArray: "6 4", opacity: 0.8 }).addTo(map) } }