import { Controller } from '@hotwired/stimulus' require("leaflet/dist/leaflet.css") import L from 'leaflet' delete L.Icon.Default.prototype._getIconUrl L.Icon.Default.mergeOptions({ iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'), iconUrl: require('leaflet/dist/images/marker-icon.png'), shadowUrl: require('leaflet/dist/images/marker-shadow.png'), }) export default class extends Controller { static targets = [ 'lat', 'lng', 'map', 'overlay' ] async connect () { this.marker() this.latTarget.addEventListener('change', event => this.marker()) this.lngTarget.addEventListener('change', event => this.marker()) window.addEventListener('resize', event => this.map.invalidateSize()) this.map.on('click', event => { this.latTarget.value = event.latlng.lat this.lngTarget.value = event.latlng.lng this.latTarget.dispatchEvent(new Event('change')) }) } marker () { if (this._marker) this.map.removeLayer(this._marker) this._marker = L.marker(this.coords).addTo(this.map) return this._marker } get lat () { const lat = parseFloat(this.latTarget.value) return isNaN(lat) ? 0 : lat } get lng () { const lng = parseFloat(this.lngTarget.value) return isNaN(lng) ? 0 : lng } get coords () { return [this.lat, this.lng] } get bounds () { return [ [0, 0], [ this.svgOverlay.viewBox.baseVal.height, this.svgOverlay.viewBox.baseVal.width, ] ]; } get map () { if (!this._map) { this._map = L.map(this.mapTarget, { minZoom: 0, maxZoom: 5 }).setView(this.coords, 0); this._layer = L.tileLayer(`${this.element.dataset.site}public/map/{z}/{y}/{x}.png`, { minNativeZoom: 0, maxNativeZoom: 5, noWrap: true }).addTo(this._map); } return this._map } }