diff --git a/.DS_Store b/.DS_Store
index 075e944..27cd34e 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..22575ea
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,99 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+`@svrnty/ngx-open-map-wrapper` is an Angular 16+ library that provides a unified map component with automatic fallback between MapLibre GL (WebGL vector maps) and Leaflet (raster maps). The library automatically detects WebGL support and chooses the optimal rendering engine.
+
+## Architecture
+
+### Adapter Pattern
+
+The library uses the **Adapter pattern** to abstract away differences between MapLibre GL and Leaflet:
+
+- **`IMapAdapter`** (map-adapter.interface.d.ts): Common interface defining map operations
+- **`LibreAdapter`** (libre-adapter.d.ts): MapLibre GL implementation
+- **`LeafletAdapter`** (leaflet-adapter.d.ts): Leaflet implementation
+- **`MapFacade`** (map-facade.d.ts): Facade that selects the appropriate adapter based on WebGL support and user preferences
+
+### Component Structure
+
+- **`OpenMapComponent`** (open-map.component.d.ts): Main Angular component that:
+ - Uses `WebglDetectionDirective` to detect WebGL support
+ - Initializes `MapFacade` with the appropriate adapter
+ - Exposes a unified API via input signals and output events
+ - Emits `mapReady` event with the `MapFacade` instance
+
+- **`WebglDetectionDirective`** (webgl-detection.directive.d.ts): Directive that detects WebGL support on the user's device and emits the result
+
+### Key Interfaces
+
+**MapOptions**:
+- `center: LatLng` - [lat, lng] tuple
+- `zoom: number`
+- `styleUrl: string` - MapLibre style URL
+- `tileUrl: string` - Tile server URL for Leaflet
+
+**Zone** (for delivery/shipping zones):
+- `id: string`
+- `name?: string`
+- `color?: string`
+- `opacity?: number`
+- `polygon: GeoPoint[]` - Array of {x, y} points
+- `shippingFee?: number`
+- `deliverySchedule?: string`
+
+**Address** (for popup display):
+- `line1, line2, postalCode, subdivision, city, country`
+- `shippingFee?: number`
+- `deliverySchedule?: string`
+
+### Core APIs
+
+Both adapters implement:
+- `init(container, options)` - Initialize map
+- `setCenter(latLng)` - Pan to location
+- `setZoom(zoom)` - Set zoom level
+- `addMarker(latLng, options?)` - Add marker with optional id/color
+- `removeMarker(id?)` - Remove specific or all markers
+- `addZone(zones)` - Add delivery zones as polygons
+- `updateZone(zones)` - Update existing zones
+- `openPopup(address)` - Show address popup
+- `closePopup()` - Hide popup
+- `on(type, event)` - Event listener
+- `destroy()` - Cleanup
+
+### Zoom Level Handling
+
+The facade includes a `leafletZoomOffset` property because MapLibre GL and Leaflet use different zoom level scales. When using Leaflet, the facade adjusts zoom levels to maintain visual consistency.
+
+## Development
+
+This is a **compiled Angular library** (not a workspace with source code). The repository contains:
+- `/lib` - TypeScript declaration files (.d.ts)
+- `/fesm2022` - Compiled ES modules
+- `package.json` - Library metadata and peer dependencies
+
+**Peer Dependencies**:
+- `@angular/common` and `@angular/core`: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+- `maplibre-gl`: ^5.0.0
+- `leaflet`: ^1.0.0 || ^2.0.0
+
+**Installation**:
+```bash
+yarn add ngx-open-open-map-wrapper leaflet maplibre-gl
+```
+
+**CSS Imports Required**:
+```css
+@import "leaflet/dist/leaflet.css";
+@import "maplibre-gl/dist/maplibre-gl.css";
+```
+
+## Recent Changes (Current Branch: feature/zone)
+
+Based on git status and recent commits:
+- Added `addZone()` and `updateZone()` methods to `IMapAdapter` interface
+- Both adapters now support zone management (delivery/shipping zones as polygons)
+- Zone objects include shipping fees and delivery schedules for e-commerce use cases
diff --git a/fesm2022/svrnty-ngx-open-map-wrapper.mjs b/fesm2022/svrnty-ngx-open-map-wrapper.mjs
index 0ea37bd..8cf7110 100644
--- a/fesm2022/svrnty-ngx-open-map-wrapper.mjs
+++ b/fesm2022/svrnty-ngx-open-map-wrapper.mjs
@@ -1,4 +1,4 @@
-import { Map, NavigationControl, Marker, GeoJSONSource } from 'maplibre-gl';
+import {Map, NavigationControl, Marker, Popup} from 'maplibre-gl';
import { Map as Map$1, TileLayer, Marker as Marker$1 } from 'leaflet';
import * as i0 from '@angular/core';
import { inject, PLATFORM_ID, output, Directive, Injector, input, runInInjectionContext, effect, ViewChild, Component } from '@angular/core';
@@ -6,263 +6,486 @@ import { isPlatformBrowser } from '@angular/common';
import {LatLng} from "leaflet/src/geo/index.js";
function getLngLat(latLng) {
- return [latLng[1], latLng[0]];
+ return [latLng[1], latLng[0]];
}
class LibreAdapter {
- map;
- init(container, options) {
- this.map = new Map({
- container,
- style: options.styleUrl,
- center: getLngLat(options.center),
- zoom: options.zoom,
- });
- this.map.addControl(new NavigationControl(), 'top-right');
+ map;
+ deliveryCheckMarker;
+ popup;
+ markers = {};
+ init(container, options) {
+ this.map = new Map({
+ container,
+ style: options.styleUrl,
+ center: getLngLat(options.center),
+ zoom: options.zoom,
+ });
+ this.map.addControl(new NavigationControl(), 'top-right');
+ }
+ setCenter(latLng) {
+ this.map.setCenter(getLngLat(latLng));
+ }
+ setZoom(zoom) {
+ this.map.setZoom(zoom);
+ }
+ addMarker(latLng, options) {
+ const coords = getLngLat(latLng);
+
+ if (options.id) {
+ if (this.markers[options.id]) {
+ this.markers[options.id].remove();
+ }
+
+ const marker = new Marker({ color: options.color || 'red' })
+ .setLngLat(coords)
+ .addTo(this.map);
+ this.markers[options.id] = marker;
+ } else {
+ if (this.deliveryCheckMarker) {
+ this.deliveryCheckMarker.remove();
+ }
+ this.deliveryCheckMarker = new Marker({ color: options?.color || 'red' })
+ .setLngLat(coords)
+ .addTo(this.map);
}
- setCenter(latLng) {
- this.map.setCenter(getLngLat(latLng));
+ }
+ removeMarker(id) {
+ if (id) {
+ if (this.markers[id]) {
+ this.markers[id].remove();
+ delete this.markers[id];
+ }
}
- setZoom(zoom) {
- this.map.setZoom(zoom);
+ else
+ {
+ if (this.deliveryCheckMarker)
+ {
+ this.deliveryCheckMarker.remove();
+ this.deliveryCheckMarker = undefined;
+ }
}
- addMarker(latLng, options) {
- new Marker({ color: options?.color || 'red' })
- .setLngLat(getLngLat(latLng))
- .addTo(this.map);
+ }
+ destroy() {
+ this.map.remove();
+ }
+ addZone(zones) {
+ this.updateZone(zones);
+ }
+ updateZone(zones) {
+ const features = zones.map((zone) => {
+ const coords = zone.polygon.map((pt) => [pt.y, pt.x]);
+
+ if (coords[0][0] !== coords[coords.length - 1][0] || coords[0][1] !== coords[coords.length - 1][1]) {
+ coords.push(coords[0]);
+ }
+
+ return {
+ type: 'Feature',
+ properties: {
+ id: zone.id,
+ name: zone.name,
+ color: zone.color ? zone.color : '#ff0000',
+ opacity: zone.opacity ? zone.opacity : 0.4,
+ },
+ geometry: {
+ type: 'Polygon',
+ coordinates: [coords]
+ },
+ };
+ });
+
+ const geojson = {
+ type: 'FeatureCollection',
+ features,
+ };
+
+ if (this.map.getSource("zones")) {
+ (this.map.getSource("zones").setData(geojson));
}
- destroy() {
- this.map.remove();
+ else {
+ this.map.addSource("zones", {
+ type: "geojson",
+ data: geojson,
+ });
+
+ this.map.addLayer({
+ id: "zones-fill",
+ type: "fill",
+ source: "zones",
+ paint: {
+ "fill-color": ["get", "color"],
+ "fill-opacity": ["get", "opacity"],
+ },
+ });
+
+ this.map.addLayer({
+ id: "zones-outline",
+ type: "line",
+ source: "zones",
+ paint: {
+ "line-color": ["get", "color"],
+ "line-width": 2,
+ },
+ });
}
- addZone(zones) {
- this.updateZone(zones);
- }
- updateZone(zones) {
- const features = zones.map((zone) => {
- const coords = zone.polygon.map((pt) => [pt.y, pt.x]);
+ }
+ openAddressPopup(address)
+ {
+ const bounds = this.map.getBounds();
+ const corner = bounds.getNorthWest();
+ this.closePopup();
+ this.popup = new Popup({
+ closeButton: false,
+ closeOnClick: false,
+ })
+ .setLngLat([corner.lng, corner.lat])
+ .setHTML(`
+
+
${address.line1}
+ ${address.line2 ? `
${address.line2}
` : ''}
+
${address.city}, ${address.postalCode}
+
${address.subdivision}, ${address.country}
+ ${address.shippingFee ? `
Shipping ${address.shippingFee}
` : ''}
+ ${address.deliverySchedule ? `
Delivery time estimate ${address.deliverySchedule}
` : ''}
+
`)
+ .addTo(this.map);
- if (coords[0][0] !== coords[coords.length - 1][0] || coords[0][1] !== coords[coords.length - 1][1]) {
- coords.push(coords[0]);
- }
+ this.map.on('move', () => {
+ if (this.popup) {
+ const newBounds = this.map.getBounds();
+ const newCorner = newBounds.getNorthWest();
+ this.popup.setLngLat([newCorner.lng, newCorner.lat]);
+ }
+ });
+ }
+ openZonePopup(zone)
+ {
+ let sumLng = 0;
+ let sumLat = 0;
+ zone.polygon.forEach(point => {
+ sumLng += point.y;
+ sumLat += point.x;
+ });
+ const centerLng = sumLng / zone.polygon.length;
+ const centerLat = sumLat / zone.polygon.length;
- return {
- type: 'Feature',
- properties: {
- id: zone.id,
- name: zone.name,
- color: zone.color ? `#${zone.color}` : '#ff0000',
- },
- geometry: {
- type: 'Polygon',
- coordinates: [coords]
- },
- };
- });
-
- const geojson = {
- type: 'FeatureCollection',
- features,
- };
-
- if (this.map.getSource("delivery-zones")) {
- (this.map.getSource("delivery-zones").setData(geojson));
- }
- else {
- this.map.addSource("delivery-zones", {
- type: "geojson",
- data: geojson,
- });
-
- this.map.addLayer({
- id: "delivery-zones-fill",
- type: "fill",
- source: "delivery-zones",
- paint: {
- "fill-color": ["get", "color"],
- "fill-opacity": 0.4,
- },
- });
-
- this.map.addLayer({
- id: "delivery-zones-outline",
- type: "line",
- source: "delivery-zones",
- paint: {
- "line-color": ["get", "color"],
- "line-width": 2,
- },
- });
- }
+ this.closePopup();
+ this.popup = new Popup({
+ closeButton: true,
+ closeOnClick: false,
+ })
+ .setLngLat([centerLng, centerLat])
+ .setHTML(`
+
+ ${zone.name ? `
${zone.name}
` : ''}
+ ${zone.shippingFee ? `
Shipping: ${zone.shippingFee}$
` : ''}
+ ${zone.deliverySchedule ? `
Delivery: ${zone.deliverySchedule}
` : ''}
+
`)
+ .addTo(this.map);
+ }
+ closePopup()
+ {
+ if (this.popup) {
+ this.popup.remove();
+ this.popup = undefined;
}
+ }
+ on(type, event,){
+ this.map.on(type, event);
+ }
}
class LeafletAdapter {
- map;
- init(container, options) {
- this.map = new Map$1(container).setView(options.center, options.zoom);
- new TileLayer(options.tileUrl, {
- attribution: '© OpenStreetMap contributors',
- }).addTo(this.map);
- }
- setCenter(latLng) {
- this.map.setView(latLng, this.map.getZoom());
- TileLayer.map
- }
- setZoom(zoom) {
- this.map.setZoom(zoom);
- }
- addMarker(latLng, options) {
- const marker = new Marker$1(latLng);
+ map;
+ deliveryCheckMarker;
+ markers = {};
+ popup;
+ init(container, options) {
+ this.map = new Map$1(container).setView(options.center, options.zoom);
+ new TileLayer(options.tileUrl, {
+ attribution: '© OpenStreetMap contributors',
+ }).addTo(this.map);
+ }
+ setCenter(latLng) {
+ this.map.setView(latLng, this.map.getZoom());
+ TileLayer.map
+ }
+ setZoom(zoom) {
+ this.map.setZoom(zoom);
+ }
+ addMarker(latLng, options) {
+ if (options.id) {
+ if (this.markers[options.id]) {
+ this.map.removeLayer(this.markers[options.id]);
+ }
+ const marker = new Marker$1(latLng)
marker.addTo(this.map);
+ this.markers[options.id] = marker;
+ } else {
+ if (this.deliveryCheckMarker) {
+ this.map.removeLayer(this.deliveryCheckMarker);
+ }
+ this.deliveryCheckMarker = new Marker$1(latLng).addTo(this.map);
}
- destroy() {
- this.map.remove();
+ }
+
+ removeMarker(id) {
+ if (id) {
+ if (this.markers[id]) {
+ this.map.removeLayer(this.markers[id]);
+ delete this.markers[id];
+ }
+ } else {
+ if (this.deliveryCheckMarker) {
+ this.map.removeLayer(this.deliveryCheckMarker);
+ this.deliveryCheckMarker = undefined;
+ }
}
- addZone(zones) {
- this.updateZone(zones);
+ }
+ destroy() {
+ this.map.remove();
+ }
+ addZone(zones) {
+ this.updateZone(zones);
+ }
+ updateZone(zones) {
+ for(let zone of zones)
+ {
+ const latlngs = zone.polygon.map((geoPoint) => {
+ return new LatLng(geoPoint.x, geoPoint.y);
+ });
+ let color = "#ff0000"
+ let opacity = 0.4;
+ if(zone.color)
+ color = zone.color;
+
+ if (zone.opacity)
+ opacity = zone.opacity;
+
+ const polygon = L.polygon(latlngs, { color, fillOpacity: opacity })
+ .addTo(this.map);
}
- updateZone(zones) {
- for(let zone of zones)
- {
- const polygon = zone.polygon.map((geoPoint) => {
- return new LatLng(geoPoint.x, geoPoint.y);
- });
- let color = "red"
- if(zone.color)
- color = `#${zone.color}`;
+ }
+ openAddressPopup(address)
+ {
+ const bounds = this.map.getBounds();
+ const corner = bounds.getNorthEast();
- this.map.polygon.push(L.polygon(polygon, {
- color
- })
- .addTo(this.map));
- }
+ if (this.popup) {
+ this.map.removeLayer(this.popup);
}
+
+ this.popup = new Marker$1(corner, {
+ opacity: 0
+ })
+ .addTo(this.map)
+ .bindTooltip(`
+
+
${address.line1}
+ ${address.line2 ? `
${address.line2}
` : ''}
+
${address.city}, ${address.postalCode}
+
${address.subdivision}, ${address.country}
+ ${address.shippingFee ? `
Shipping ${address.shippingFee}
` : ''}
+ ${address.deliverySchedule ? `
Delivery time estimate ${address.deliverySchedule}
` : ''}
+
`,
+ {
+ permanent: true,
+ offset: [-38, 135]
+ })
+ .openTooltip();
+
+ this.map.on('move', () => {
+ if (this.popup) {
+ const newBounds = this.map.getBounds();
+ const newCorner = newBounds.getNorthEast();
+ this.popup.setLatLng(newCorner);
+ }
+ });
+
+ }
+ openZonePopup(zone)
+ {
+ let sumLat = 0;
+ let sumLng = 0;
+ zone.polygon.forEach(point => {
+ sumLat += point.x;
+ sumLng += point.y;
+ });
+ const centerLat = sumLat / zone.polygon.length;
+ const centerLng = sumLng / zone.polygon.length;
+
+ if (this.popup) {
+ this.map.removeLayer(this.popup);
+ }
+
+ this.popup = new Marker$1([centerLat, centerLng], {
+ opacity: 0
+ })
+ .addTo(this.map)
+ .bindTooltip(`
+
+ ${zone.name ? `
${zone.name}
` : ''}
+ ${zone.shippingFee ? `
Shipping: ${zone.shippingFee}
` : ''}
+ ${zone.deliverySchedule ? `
Delivery: ${zone.deliverySchedule}
` : ''}
+
`,
+ {
+ permanent: true,
+ offset: [0, 0]
+ })
+ .openTooltip();
+ }
+ closePopup()
+ {
+ if (this.popup) {
+ this.map.removeLayer(this.popup);
+ this.popup = undefined;
+ }
+ }
+ on(type, event) {
+ this.map.on(type, event);
+ }
}
class MapFacade {
- adapter;
- leafletZoomOffset = 1;
- constructor(forceRaster, webglAvailable) {
- if (forceRaster || !webglAvailable) {
- this.adapter = new LeafletAdapter();
- }
- else {
- this.adapter = new LibreAdapter();
- }
+ adapter;
+ leafletZoomOffset = 1;
+ constructor(forceRaster, webglAvailable) {
+ if (forceRaster || !webglAvailable) {
+ this.adapter = new LeafletAdapter();
}
- init(container, options) {
- if (this.adapter instanceof LeafletAdapter)
- options.zoom += this.leafletZoomOffset;
- this.adapter.init(container, options);
- }
- setCenter(latLng) {
- this.adapter.setCenter(latLng);
- }
- setZoom(zoom) {
- if (this.adapter instanceof LeafletAdapter)
- zoom += this.leafletZoomOffset;
- this.adapter.setZoom(zoom);
- }
- addMarker(latLng, options) {
- this.adapter.addMarker(latLng, options);
- }
- destroy() {
- this.adapter.destroy();
- }
- addZone(deliveryZones) {
- this.adapter.addZone(deliveryZones);
- }
- updateZone(deliveryZones) {
- this.adapter.updateZone(deliveryZones);
+ else {
+ this.adapter = new LibreAdapter();
}
+ }
+ init(container, options) {
+ if (this.adapter instanceof LeafletAdapter)
+ options.zoom += this.leafletZoomOffset;
+ this.adapter.init(container, options);
+ }
+ setCenter(latLng) {
+ this.adapter.setCenter(latLng);
+ }
+ setZoom(zoom) {
+ if (this.adapter instanceof LeafletAdapter)
+ zoom += this.leafletZoomOffset;
+ this.adapter.setZoom(zoom);
+ }
+ addMarker(latLng, options) {
+ this.adapter.addMarker(latLng, options);
+ }
+ removeMarker() {
+ this.adapter.removeMarker();
+ }
+ destroy() {
+ this.adapter.destroy();
+ }
+ addZone(zones) {
+ this.adapter.addZone(zones);
+ }
+ updateZone(zones) {
+ this.adapter.updateZone(zones);
+ }
+ openAddressPopup(deliveryAddress) {
+ this.adapter.openAddressPopup(deliveryAddress);
+ }
+ openZonePopup(zone) {
+ this.adapter.openZonePopup(zone);
+ }
+ closePopup() {
+ this.adapter.closePopup();
+ }
+ on(type, event,){
+ this.adapter.on(type, event);
+ }
}
class WebglDetectionDirective {
- platformId = inject(PLATFORM_ID);
- webglSupport = output();
- ngOnInit() {
- if (!isPlatformBrowser(this.platformId))
- return;
- const supported = this.checkWebGLSupport();
- this.webglSupport.emit(supported);
+ platformId = inject(PLATFORM_ID);
+ webglSupport = output();
+ ngOnInit() {
+ if (!isPlatformBrowser(this.platformId))
+ return;
+ const supported = this.checkWebGLSupport();
+ this.webglSupport.emit(supported);
+ }
+ checkWebGLSupport() {
+ let canvas = undefined;
+ try {
+ canvas = document.createElement('canvas');
+ const gl = (canvas.getContext('webgl') ||
+ canvas.getContext('experimental-webgl'));
+ const supported = !!window.WebGLRenderingContext &&
+ !!(gl);
+ return supported;
}
- checkWebGLSupport() {
- let canvas = undefined;
- try {
- canvas = document.createElement('canvas');
- const gl = (canvas.getContext('webgl') ||
- canvas.getContext('experimental-webgl'));
- const supported = !!window.WebGLRenderingContext &&
- !!(gl);
- return supported;
- }
- catch {
- return false;
- }
- finally {
- canvas?.remove();
- }
+ catch {
+ return false;
}
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: WebglDetectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: WebglDetectionDirective, isStandalone: true, selector: "[webglDetection]", outputs: { webglSupport: "webglSupport" }, ngImport: i0 });
+ finally {
+ canvas?.remove();
+ }
+ }
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: WebglDetectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: WebglDetectionDirective, isStandalone: true, selector: "[webglDetection]", outputs: { webglSupport: "webglSupport" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: WebglDetectionDirective, decorators: [{
- type: Directive,
- args: [{
- selector: '[webglDetection]',
- standalone: true
- }]
- }] });
+ type: Directive,
+ args: [{
+ selector: '[webglDetection]',
+ standalone: true
+ }]
+ }] });
class OpenMapComponent {
- platformId = inject(PLATFORM_ID);
- injector = inject(Injector);
- webglSupported;
- map;
- mapContainer;
- options = input({
- center: [50.426606229502525, 30.56308375468811],
- zoom: 6,
- styleUrl: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
- tileUrl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
- forceRaster: false,
+ platformId = inject(PLATFORM_ID);
+ injector = inject(Injector);
+ webglSupported;
+ map;
+ mapContainer;
+ options = input({
+ center: [50.426606229502525, 30.56308375468811],
+ zoom: 6,
+ styleUrl: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
+ tileUrl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
+ forceRaster: false,
+ });
+ mapReady = output();
+ ngAfterViewInit() {
+ if (false === isPlatformBrowser(this.platformId))
+ return;
+ runInInjectionContext(this.injector, () => {
+ effect(() => {
+ if (undefined === this.webglSupported)
+ return;
+ if (!this.map)
+ this.initializeMap();
+ });
});
- mapReady = output();
- ngAfterViewInit() {
- if (false === isPlatformBrowser(this.platformId))
- return;
- runInInjectionContext(this.injector, () => {
- effect(() => {
- if (undefined === this.webglSupported)
- return;
- if (!this.map)
- this.initializeMap();
- });
- });
- }
- webglDetection(supported) {
- this.webglSupported = supported;
- if (undefined === this.map)
- this.initializeMap();
- }
- initializeMap() {
- const options = this.options();
- this.map = new MapFacade(options.forceRaster, this.webglSupported);
- this.map.init(this.mapContainer.nativeElement, options);
- this.mapReady.emit(this.map);
- }
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: OpenMapComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.14", type: OpenMapComponent, isStandalone: true, selector: "open-map", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { mapReady: "mapReady" }, viewQueries: [{ propertyName: "mapContainer", first: true, predicate: ["mapContainer"], descendants: true, static: true }], ngImport: i0, template: "\n\n
\n", styles: [".map-container{width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: WebglDetectionDirective, selector: "[webglDetection]", outputs: ["webglSupport"] }] });
+ }
+ webglDetection(supported) {
+ this.webglSupported = supported;
+ if (undefined === this.map)
+ this.initializeMap();
+ }
+ initializeMap() {
+ const options = this.options();
+ this.map = new MapFacade(options.forceRaster, this.webglSupported);
+ this.map.init(this.mapContainer.nativeElement, options);
+ this.mapReady.emit(this.map);
+ }
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: OpenMapComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.14", type: OpenMapComponent, isStandalone: true, selector: "open-map", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { mapReady: "mapReady" }, viewQueries: [{ propertyName: "mapContainer", first: true, predicate: ["mapContainer"], descendants: true, static: true }], ngImport: i0, template: "\n\n
\n", styles: [".map-container{width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: WebglDetectionDirective, selector: "[webglDetection]", outputs: ["webglSupport"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: OpenMapComponent, decorators: [{
- type: Component,
- args: [{ selector: 'open-map', imports: [
- WebglDetectionDirective
- ], standalone: true, template: "\n\n
\n", styles: [".map-container{width:100%;height:100%}\n"] }]
- }], propDecorators: { mapContainer: [{
- type: ViewChild,
- args: ['mapContainer', { static: true }]
- }] } });
+ type: Component,
+ args: [{ selector: 'open-map', imports: [
+ WebglDetectionDirective
+ ], standalone: true, template: "\n\n
\n", styles: [".map-container{width:100%;height:100%}\n"] }]
+ }], propDecorators: { mapContainer: [{
+ type: ViewChild,
+ args: ['mapContainer', { static: true }]
+ }] } });
/*
* Public API Surface of ngx-open-open-map-wrapper
diff --git a/lib/adapters/leaflet-adapter.d.ts b/lib/adapters/leaflet-adapter.d.ts
index f0fb5fa..d48d0df 100644
--- a/lib/adapters/leaflet-adapter.d.ts
+++ b/lib/adapters/leaflet-adapter.d.ts
@@ -1,13 +1,19 @@
-import {DeliveryZone, IMapAdapter, LatLng, MapOptions} from './map-adapter.interface';
+import {Zone, IMapAdapter, LatLng, MapOptions, Address} from './map-adapter.interface';
export declare class LeafletAdapter implements IMapAdapter {
- private map;
- init(container: HTMLElement, options: MapOptions): void;
- setCenter(latLng: LatLng): void;
- setZoom(zoom: number): void;
- addMarker(latLng: LatLng, options?: {
- color?: string;
- }): void;
- destroy(): void;
- addZone(zone: DeliveryZone[]): void;
- updateZone(one: DeliveryZone[]): void;
+ private map;
+ private deliveryCheckMarker?;
+ private markers?: {};
+ private popup?;
+ init(container: HTMLElement, options: MapOptions): void;
+ setCenter(latLng: LatLng): void;
+ setZoom(zoom: number): void;
+ addMarker(latLng: LatLng, options?: { id?: string; color?: string }): void;
+ removeMarker(id?: string): void;
+ destroy(): void;
+ addZone(zone: Zone[]): void;
+ updateZone(zone: Zone[]): void;
+ openZonePopup(zone: Zone) : void
+ openAddressPopup(address: Address): void;
+ closePopup(): void;
+ on(type: string, event: (e: any) => void): void;
}
diff --git a/lib/adapters/libre-adapter.d.ts b/lib/adapters/libre-adapter.d.ts
index f2d5e0d..9c13381 100644
--- a/lib/adapters/libre-adapter.d.ts
+++ b/lib/adapters/libre-adapter.d.ts
@@ -1,13 +1,19 @@
-import {DeliveryZone, IMapAdapter, LatLng, MapOptions} from './map-adapter.interface';
+import {Address, IMapAdapter, LatLng, MapOptions, Zone} from './map-adapter.interface';
export declare class LibreAdapter implements IMapAdapter {
- private map;
- init(container: HTMLElement, options: MapOptions): void;
- setCenter(latLng: LatLng): void;
- setZoom(zoom: number): void;
- addMarker(latLng: LatLng, options?: {
- color?: string;
- }): void;
- destroy(): void;
- addZone(zone: DeliveryZone[]): void;
- updateZone(one: DeliveryZone[]): void;
+ private map;
+ private deliveryCheckMarker?;
+ private markers?: {};
+ private popup?;
+ init(container: HTMLElement, options: MapOptions): void;
+ setCenter(latLng: LatLng): void;
+ setZoom(zoom: number): void;
+ addMarker(latLng: LatLng, options?: { id?: string; color?: string }): void;
+ removeMarker(id?: string): void;
+ destroy(): void;
+ addZone(zone: Zone[]): void;
+ updateZone(zone: Zone[]): void;
+ openZonePopup(zone: Zone) : void
+ openAddressPopup(address: Address): void;
+ closePopup(): void;
+ on(type: string, event: (e: any) => void): void;
}
diff --git a/lib/adapters/map-adapter.interface.d.ts b/lib/adapters/map-adapter.interface.d.ts
index 54f9f0d..9465b5f 100644
--- a/lib/adapters/map-adapter.interface.d.ts
+++ b/lib/adapters/map-adapter.interface.d.ts
@@ -1,32 +1,51 @@
-import * as maplibregl from 'maplibre-gl';
-import * as L from 'leaflet';
+
export interface MapOptions {
- center: LatLng;
- zoom: number;
- styleUrl: string;
- tileUrl: string;
+ center: LatLng;
+ zoom: number;
+ styleUrl: string;
+ tileUrl: string;
}
export interface GeoPoint {
- x: number;
- y: number;
+ x: number;
+ y: number;
}
-export interface DeliveryZone {
- id: string;
- name?: string;
- color?: string;
- polygon: GeoPoint[];
+export interface Zone {
+ id: string;
+ name?: string;
+ color?: string;
+ opacity?: number;
+ polygon: GeoPoint[];
+ shippingFee?: number;
+ deliverySchedule?: string;
+}
+export interface Address {
+ line1: string;
+ line2?: string;
+ postalCode: string;
+ subdivision: string;
+ city: string;
+ country: string;
+ shippingFee?: number;
+ deliverySchedule?: string;
}
export type LatLng = [number, number];
export declare function getLngLat(latLng: LatLng): [number, number];
export interface IMapAdapter {
- init(container: HTMLElement, options: MapOptions): void;
- setCenter(latLng: LatLng): void;
- setZoom(zoom: number): void;
- addMarker(latLng: LatLng, options?: {
- color?: string;
- }): void;
- destroy(): void;
- addZone(zone: DeliveryZone[]): void;
- updateZone(one: DeliveryZone[]): void;
+ init(container: HTMLElement, options: MapOptions): void;
+ setCenter(latLng: LatLng): void;
+ setZoom(zoom: number): void;
+ addMarker(latLng: LatLng, options?: { id?: string; color?: string }): void;
+ removeMarker(id?: string): void;
+ destroy(): void;
+ addZone(zone: Zone[]): void;
+ updateZone(zone: Zone[]): void;
+ openZonePopup(zone: Zone) : void
+ openAddressPopup(address: Address): void;
+ closePopup(): void;
+ on(
+ type: string,
+ event: (e: any) => void,
+ ): void;
+
}
diff --git a/lib/adapters/map-facade.d.ts b/lib/adapters/map-facade.d.ts
index 76c1226..09a949d 100644
--- a/lib/adapters/map-facade.d.ts
+++ b/lib/adapters/map-facade.d.ts
@@ -1,15 +1,18 @@
-import {IMapAdapter, MapOptions, LatLng, DeliveryZone} from './map-adapter.interface';
+import {IMapAdapter, MapOptions, LatLng, Zone, Address} from './map-adapter.interface';
export declare class MapFacade implements IMapAdapter {
- private readonly adapter;
- private readonly leafletZoomOffset;
- constructor(forceRaster: boolean, webglAvailable: boolean);
- init(container: HTMLElement, options: MapOptions): void;
- setCenter(latLng: LatLng): void;
- setZoom(zoom: number): void;
- addMarker(latLng: LatLng, options?: {
- color?: string;
- }): void;
- destroy(): void;
- addZone(zone: DeliveryZone[]): void;
- updateZone(one: DeliveryZone[]): void;
+ private readonly adapter;
+ private readonly leafletZoomOffset;
+ constructor(forceRaster: boolean, webglAvailable: boolean);
+ init(container: HTMLElement, options: MapOptions): void;
+ setCenter(latLng: LatLng): void;
+ setZoom(zoom: number): void;
+ addMarker(latLng: LatLng, options?: { id?: string; color?: string }): void;
+ removeMarker(id?: string): void;
+ destroy(): void;
+ addZone(zone: Zone[]): void;
+ updateZone(zone: Zone[]): void;
+ openZonePopup(zone: Zone) : void
+ openAddressPopup(address: Address): void;
+ closePopup(): void;
+ on(type: string, event: (e: any) => void): void;
}
diff --git a/lib/components/open-map/open-map.component.d.ts b/lib/components/open-map/open-map.component.d.ts
index 4c19c19..29b5bf7 100644
--- a/lib/components/open-map/open-map.component.d.ts
+++ b/lib/components/open-map/open-map.component.d.ts
@@ -3,19 +3,19 @@ import { MapOptions } from '../../adapters/map-adapter.interface';
import { MapFacade } from '../../adapters/map-facade';
import * as i0 from "@angular/core";
export interface OpenMapOptions extends MapOptions {
- forceRaster: boolean;
+ forceRaster: boolean;
}
export declare class OpenMapComponent implements AfterViewInit {
- private readonly platformId;
- private readonly injector;
- webglSupported?: boolean;
- map?: MapFacade;
- mapContainer: ElementRef;
- options: import("@angular/core").InputSignal;
- mapReady: import("@angular/core").OutputEmitterRef;
- ngAfterViewInit(): void;
- webglDetection(supported: boolean): void;
- private initializeMap;
- static ɵfac: i0.ɵɵFactoryDeclaration;
- static ɵcmp: i0.ɵɵComponentDeclaration;
+ private readonly platformId;
+ private readonly injector;
+ webglSupported?: boolean;
+ map?: MapFacade;
+ mapContainer: ElementRef;
+ options: import("@angular/core").InputSignal;
+ mapReady: import("@angular/core").OutputEmitterRef;
+ ngAfterViewInit(): void;
+ webglDetection(supported: boolean): void;
+ private initializeMap;
+ static ɵfac: i0.ɵɵFactoryDeclaration;
+ static ɵcmp: i0.ɵɵComponentDeclaration;
}
diff --git a/lib/directives/webgl-detection.directive.d.ts b/lib/directives/webgl-detection.directive.d.ts
index b1b965c..634cdab 100644
--- a/lib/directives/webgl-detection.directive.d.ts
+++ b/lib/directives/webgl-detection.directive.d.ts
@@ -1,10 +1,10 @@
import { OnInit } from '@angular/core';
import * as i0 from "@angular/core";
export declare class WebglDetectionDirective implements OnInit {
- private readonly platformId;
- webglSupport: import("@angular/core").OutputEmitterRef;
- ngOnInit(): void;
- private checkWebGLSupport;
- static ɵfac: i0.ɵɵFactoryDeclaration;
- static ɵdir: i0.ɵɵDirectiveDeclaration;
+ private readonly platformId;
+ webglSupport: import("@angular/core").OutputEmitterRef;
+ ngOnInit(): void;
+ private checkWebGLSupport;
+ static ɵfac: i0.ɵɵFactoryDeclaration;
+ static ɵdir: i0.ɵɵDirectiveDeclaration;
}