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; }