ng-leaflet-universal-cm
Version:
NgLeafletUniversal is an open source Angular module that extends and simplifies the Leaflet implementation for Angular.
159 lines (152 loc) • 10.9 kB
JavaScript
import { map, tileLayer, FeatureGroup, Marker, divIcon } from 'leaflet';
import * as i0 from '@angular/core';
import { output, input, effect, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
function generate(prefix = 'ng-leaflet-universal') {
const hexstring = Math.random().toString(16).slice(2);
return [prefix, hexstring].filter(Boolean).join('-');
}
const getCardHtml = (card) => card?.customHtml
? card.customHtml
: `
<div class="map-card">
<div class="map-card-body">
<div class="top-card">
<img src="${card?.image?.url}" alt="${card?.title?.text}" />
<div class="content">
<h2 class="map-card-title">${card?.title?.text}</h2>
<h4 class="map-card-subtitle">${card?.subtitle?.text}</h4>
<h5 class="map-address">${card?.address?.text}</h5>
</div>
</div>
<div class="map-card-content">
${card?.content?.text}
</div>
<div class="cta-wrapper">
${card?.callToActions
?.map((cta) => `
<a href="${cta.link}"
target="_blank"
style="
background-color: ${cta.backgroundColor || '#007FFF'};
color: ${cta.textColor || 'white'};"
class="map-card-cta">
${cta.icon ? `<i class="${cta.icon}"></i>` : ''}
${cta.text}</a>
`)
.reduce((a, b) => a + b)}
</div>
</div>
</div>`;
class MapComponent {
constructor() {
this.mapEvent = output();
this.markers = input([]);
this.id = generate('div');
this.#effet = effect(() => {
if (this.map) {
this.updateMarkers(this.markers());
}
});
}
#effet;
ngAfterViewInit() {
this.map = map(this.id).setView([18.4, -66.9], 4);
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © OpenStreetMap contributors',
}).addTo(this.map);
this.updateMarkers(this.markers());
}
removeMarkers() {
this.map.eachLayer((layer) => {
// Ignore tile layer
if (layer.options?.attribution)
return;
// Previous (markers)
layer.remove();
});
}
updateMarkers(markers) {
this.removeMarkers();
if (!markers?.length)
return;
const leafletMarkers = markers.map(createLeafletMarker).map((marker, i) => {
return marker.on('click', () => this.mapEvent.emit(markers[i]));
});
const group = new FeatureGroup(leafletMarkers);
group.addTo(this.map);
this.map.fitBounds(group.getBounds());
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MapComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.6", type: MapComponent, isStandalone: false, selector: "ng-leaflet-universal", inputs: { markers: { classPropertyName: "markers", publicName: "markers", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { mapEvent: "mapEvent" }, ngImport: i0, template: `
<div class="map">
<div class="map-frame">
<div [id]="id"></div>
</div>
</div>
`, isInline: true, styles: [".map{position:absolute;inset:0}.map .map-frame,.map .map-frame div{height:100%}::ng-deep .leaflet-popup-tip{border-radius:0 0 20%!important}::ng-deep .map-marker-icon .item-marker{border-radius:100% 100% 100% 35%;border:2px solid #444444;width:22px!important;height:22px!important;background-color:#444;box-shadow:0 0 3px #0000005d;transform:rotate(-45deg);overflow:hidden}::ng-deep .map-marker-icon .item-marker .icon-image{width:100%;height:100%;border-radius:100%;background-position:center;background-size:cover;transform:rotate(38deg)}::ng-deep .leaflet-container a.leaflet-popup-close-button{position:absolute;top:5px;right:5px;padding:3px!important;color:#ff0f0f98;text-decoration:none;font-weight:700;background:#f2f2f2}::ng-deep .leaflet-container a.leaflet-popup-close-button:hover{color:#ff0f0f}::ng-deep .leaflet-popup{bottom:32px!important}::ng-deep .leaflet-popup-content{min-width:350px!important;height:auto!important}::ng-deep .leaflet-popup-content .map-card .map-card-body{padding:10px}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card{display:flex;align-items:center}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card img{width:100px;height:100px;margin-right:20px}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-title{font-weight:700;margin:0}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-subtitle{font-weight:400;font-size:14px;color:#585858;margin:0}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-content h4{font-size:16px}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-content p{font-size:14px}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper{margin-top:20px;width:100%;display:grid;grid-template-columns:repeat(3,1fr);grid-gap:15px}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper .map-card-cta{cursor:pointer;text-decoration:none;border:none;padding:8px 10px;font-size:12px;text-align:center;margin-bottom:6px;height:20px;display:flex;justify-content:center;align-items:center;border-radius:2px}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper .map-card-cta:hover{opacity:.6}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper .map-card-cta i{margin-right:5px;font-size:10px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MapComponent, decorators: [{
type: Component,
args: [{ selector: 'ng-leaflet-universal', template: `
<div class="map">
<div class="map-frame">
<div [id]="id"></div>
</div>
</div>
`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, styles: [".map{position:absolute;inset:0}.map .map-frame,.map .map-frame div{height:100%}::ng-deep .leaflet-popup-tip{border-radius:0 0 20%!important}::ng-deep .map-marker-icon .item-marker{border-radius:100% 100% 100% 35%;border:2px solid #444444;width:22px!important;height:22px!important;background-color:#444;box-shadow:0 0 3px #0000005d;transform:rotate(-45deg);overflow:hidden}::ng-deep .map-marker-icon .item-marker .icon-image{width:100%;height:100%;border-radius:100%;background-position:center;background-size:cover;transform:rotate(38deg)}::ng-deep .leaflet-container a.leaflet-popup-close-button{position:absolute;top:5px;right:5px;padding:3px!important;color:#ff0f0f98;text-decoration:none;font-weight:700;background:#f2f2f2}::ng-deep .leaflet-container a.leaflet-popup-close-button:hover{color:#ff0f0f}::ng-deep .leaflet-popup{bottom:32px!important}::ng-deep .leaflet-popup-content{min-width:350px!important;height:auto!important}::ng-deep .leaflet-popup-content .map-card .map-card-body{padding:10px}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card{display:flex;align-items:center}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card img{width:100px;height:100px;margin-right:20px}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-title{font-weight:700;margin:0}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-subtitle{font-weight:400;font-size:14px;color:#585858;margin:0}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-content h4{font-size:16px}::ng-deep .leaflet-popup-content .map-card .map-card-body .top-card .content .map-card-content p{font-size:14px}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper{margin-top:20px;width:100%;display:grid;grid-template-columns:repeat(3,1fr);grid-gap:15px}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper .map-card-cta{cursor:pointer;text-decoration:none;border:none;padding:8px 10px;font-size:12px;text-align:center;margin-bottom:6px;height:20px;display:flex;justify-content:center;align-items:center;border-radius:2px}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper .map-card-cta:hover{opacity:.6}::ng-deep .leaflet-popup-content .map-card .map-card-body .cta-wrapper .map-card-cta i{margin-right:5px;font-size:10px}\n"] }]
}] });
function createLeafletMarker(marker) {
const leafletMarker = new Marker({
lat: marker.location.latitude,
lng: marker.location.longitude,
});
leafletMarker.setIcon(divIcon({
html: marker.html ||
`
<div class="item-marker">
<div class="icon-image" style="background-image: url('${marker.icon}')">
</div>
</div>`,
className: 'map-marker-icon',
iconSize: [26, 30],
iconAnchor: [13, 30],
}));
leafletMarker.on('click', function ({ target, latlng }) {
if (marker.cardActivated && marker?.card) {
const html = getCardHtml(marker.card);
const popup = target.getPopup();
if (popup)
popup?.openPopup();
else {
target
.bindPopup(html, {
autoClose: false,
maxWidth: 200,
})
.openPopup();
}
}
target._map.setView(latlng, 15);
});
return leafletMarker;
}
class NgLeafletUniversalModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: NgLeafletUniversalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.6", ngImport: i0, type: NgLeafletUniversalModule, declarations: [MapComponent], exports: [MapComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: NgLeafletUniversalModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: NgLeafletUniversalModule, decorators: [{
type: NgModule,
args: [{
declarations: [MapComponent],
exports: [MapComponent],
}]
}] });
/*
* Public API Surface of ng-leaflet-universal
*/
/**
* Generated bundle index. Do not edit.
*/
export { MapComponent, NgLeafletUniversalModule };
//# sourceMappingURL=ng-leaflet-universal-cm.mjs.map