@angular-helpers/openlayers 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,29 +1,51 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, input, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { inject, signal, computed, Injectable, DestroyRef, input, afterNextRender, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import VectorLayer from 'ol/layer/Vector';
4
4
  import TileLayer from 'ol/layer/Tile';
5
5
  import ImageLayer from 'ol/layer/Image';
6
6
  import VectorSource from 'ol/source/Vector';
7
+ import { Feature } from 'ol';
8
+ import { Point, LineString, Polygon, Circle } from 'ol/geom';
9
+ import { fromLonLat } from 'ol/proj';
10
+ import { Style, Circle as Circle$1, Stroke, Fill } from 'ol/style';
7
11
  import OSM from 'ol/source/OSM';
8
12
  import XYZ from 'ol/source/XYZ';
9
13
  import TileWMS from 'ol/source/TileWMS';
10
14
  import ImageWMS from 'ol/source/ImageWMS';
15
+ import { ImageStatic } from 'ol/source';
11
16
  import { OlMapService } from '@angular-helpers/openlayers/core';
12
17
 
13
18
  // OlLayerService
14
19
  class OlLayerService {
15
20
  mapService = inject(OlMapService);
16
21
  layerCache = new Map();
22
+ pendingConfigs = [];
23
+ layerState = signal([], ...(ngDevMode ? [{ debugName: "layerState" }] : /* istanbul ignore next */ []));
24
+ layers = computed(() => this.layerState(), ...(ngDevMode ? [{ debugName: "layers" }] : /* istanbul ignore next */ []));
25
+ visibleLayers = computed(() => this.layerState().filter((l) => l.visible), ...(ngDevMode ? [{ debugName: "visibleLayers" }] : /* istanbul ignore next */ []));
26
+ tileLayers = computed(() => this.layerState().filter((l) => l.type === 'tile'), ...(ngDevMode ? [{ debugName: "tileLayers" }] : /* istanbul ignore next */ []));
27
+ vectorLayers = computed(() => this.layerState().filter((l) => l.type === 'vector'), ...(ngDevMode ? [{ debugName: "vectorLayers" }] : /* istanbul ignore next */ []));
17
28
  addLayer(config) {
18
- // If layer already exists, return it (idempotent for retries)
19
29
  if (this.layerCache.has(config.id)) {
20
30
  return { id: config.id };
21
31
  }
22
32
  const map = this.mapService.getMap();
23
33
  if (!map) {
24
- // Map not ready yet - caller should retry
34
+ this.pendingConfigs.push(config);
35
+ this.mapService.onReady((readyMap) => this.flushPending(readyMap));
25
36
  return { id: config.id };
26
37
  }
38
+ return this.createLayer(config, map);
39
+ }
40
+ flushPending(map) {
41
+ const pending = this.pendingConfigs.splice(0);
42
+ for (const config of pending) {
43
+ if (!this.layerCache.has(config.id)) {
44
+ this.createLayer(config, map);
45
+ }
46
+ }
47
+ }
48
+ createLayer(config, map) {
27
49
  switch (config.type) {
28
50
  case 'vector':
29
51
  return this.createVectorLayer(config, map);
@@ -35,30 +57,213 @@ class OlLayerService {
35
57
  return { id: config.id };
36
58
  }
37
59
  }
60
+ getLayer(id) {
61
+ return this.layerCache.get(id);
62
+ }
63
+ hasLayer(id) {
64
+ return this.layerCache.has(id);
65
+ }
38
66
  removeLayer(id) {
67
+ // Cancel if it's still pending (map not ready yet)
68
+ const pendingIdx = this.pendingConfigs.findIndex((c) => c.id === id);
69
+ if (pendingIdx !== -1) {
70
+ this.pendingConfigs.splice(pendingIdx, 1);
71
+ return;
72
+ }
39
73
  const map = this.mapService.getMap();
40
74
  const layer = this.layerCache.get(id);
41
75
  if (map && layer) {
42
76
  map.removeLayer(layer);
43
77
  this.layerCache.delete(id);
78
+ this.updateLayerState();
44
79
  }
45
80
  }
46
81
  setVisibility(id, visible) {
47
- this.layerCache.get(id)?.setVisible(visible);
82
+ const layer = this.layerCache.get(id);
83
+ if (layer) {
84
+ layer.setVisible(visible);
85
+ this.updateLayerState();
86
+ }
87
+ }
88
+ toggleVisibility(id) {
89
+ const layer = this.layerCache.get(id);
90
+ if (layer) {
91
+ const newVisible = !layer.getVisible();
92
+ layer.setVisible(newVisible);
93
+ this.updateLayerState();
94
+ return newVisible;
95
+ }
96
+ return false;
48
97
  }
49
98
  setOpacity(id, opacity) {
50
- this.layerCache.get(id)?.setOpacity(opacity);
99
+ const layer = this.layerCache.get(id);
100
+ if (layer) {
101
+ layer.setOpacity(opacity);
102
+ this.updateLayerState();
103
+ }
104
+ }
105
+ setZIndex(id, zIndex) {
106
+ const layer = this.layerCache.get(id);
107
+ if (layer) {
108
+ layer.setZIndex(zIndex);
109
+ this.updateLayerState();
110
+ }
111
+ }
112
+ isVisible(id) {
113
+ return this.layerCache.get(id)?.getVisible() ?? false;
114
+ }
115
+ getOpacity(id) {
116
+ return this.layerCache.get(id)?.getOpacity() ?? 1;
117
+ }
118
+ getZIndex(id) {
119
+ return this.layerCache.get(id)?.getZIndex() ?? 0;
120
+ }
121
+ /**
122
+ * Clears all features from a vector layer's source.
123
+ * Does not remove the layer itself.
124
+ * @param id - Layer identifier
125
+ */
126
+ clearFeatures(id) {
127
+ const layer = this.layerCache.get(id);
128
+ if (!(layer instanceof VectorLayer))
129
+ return;
130
+ layer.getSource()?.clear();
131
+ }
132
+ /**
133
+ * Updates the features of a vector layer.
134
+ * Syncs new features without clearing existing ones (preserves OL modifications).
135
+ * @param id - Layer identifier
136
+ * @param features - New features to sync
137
+ */
138
+ updateFeatures(id, features) {
139
+ const layer = this.layerCache.get(id);
140
+ if (!(layer instanceof VectorLayer))
141
+ return;
142
+ const source = layer.getSource();
143
+ if (!source)
144
+ return;
145
+ // Get existing feature IDs from source
146
+ const existingIds = new Set(source
147
+ .getFeatures()
148
+ .map((f) => f.getId())
149
+ .filter((id) => id !== undefined));
150
+ // Only add features that don't already exist in the source
151
+ if (features && features.length > 0) {
152
+ const newFeatures = features.filter((f) => !existingIds.has(f.id));
153
+ if (newFeatures.length > 0) {
154
+ const olFeatures = newFeatures.map((feature) => {
155
+ const geom = feature.geometry;
156
+ let geometry;
157
+ // Validate coordinates exist before processing
158
+ if (!geom.coordinates) {
159
+ geometry = new Point([0, 0]);
160
+ }
161
+ else if (geom.type === 'Point') {
162
+ const coords = geom.coordinates;
163
+ geometry = new Point(fromLonLat(coords));
164
+ }
165
+ else if (geom.type === 'LineString') {
166
+ const coords = geom.coordinates.map((c) => fromLonLat(c));
167
+ geometry = new LineString(coords);
168
+ }
169
+ else if (geom.type === 'Polygon') {
170
+ const rings = geom.coordinates.map((ring) => ring.map((c) => fromLonLat(c)));
171
+ geometry = new Polygon(rings);
172
+ }
173
+ else if (geom.type === 'Circle') {
174
+ const center = fromLonLat(geom.coordinates);
175
+ // Approximate radius in meters - use 1000m as default if not specified
176
+ geometry = new Circle(center, geom.radius ?? 1000);
177
+ }
178
+ else {
179
+ geometry = new Point([0, 0]);
180
+ }
181
+ const olFeature = new Feature({
182
+ geometry,
183
+ ...feature.properties,
184
+ });
185
+ olFeature.setId(feature.id);
186
+ return olFeature;
187
+ });
188
+ source.addFeatures(olFeatures);
189
+ }
190
+ }
191
+ }
192
+ updateLayerState() {
193
+ const layers = [];
194
+ this.layerCache.forEach((layer, id) => {
195
+ const type = layer instanceof VectorLayer ? 'vector' : layer instanceof TileLayer ? 'tile' : 'image';
196
+ layers.push({
197
+ id,
198
+ type: type,
199
+ visible: layer.getVisible(),
200
+ opacity: layer.getOpacity(),
201
+ zIndex: layer.getZIndex() ?? 0,
202
+ });
203
+ });
204
+ this.layerState.set(layers.sort((a, b) => a.zIndex - b.zIndex));
51
205
  }
52
206
  createVectorLayer(config, map) {
207
+ const source = new VectorSource();
208
+ // Add features if provided
209
+ if (config.features && config.features.length > 0) {
210
+ const olFeatures = config.features.map((feature) => {
211
+ const geom = feature.geometry;
212
+ let geometry;
213
+ // Validate coordinates exist before processing
214
+ if (!geom.coordinates) {
215
+ geometry = new Point([0, 0]);
216
+ }
217
+ else if (geom.type === 'Point') {
218
+ // Transform from EPSG:4326 (lon/lat) to EPSG:3857 (map projection)
219
+ const coords = geom.coordinates;
220
+ geometry = new Point(fromLonLat(coords));
221
+ }
222
+ else if (geom.type === 'LineString') {
223
+ const coords = geom.coordinates.map((c) => fromLonLat(c));
224
+ geometry = new LineString(coords);
225
+ }
226
+ else if (geom.type === 'Polygon') {
227
+ const rings = geom.coordinates.map((ring) => ring.map((c) => fromLonLat(c)));
228
+ geometry = new Polygon(rings);
229
+ }
230
+ else if (geom.type === 'Circle') {
231
+ const center = fromLonLat(geom.coordinates);
232
+ geometry = new Circle(center, geom.radius ?? 1000);
233
+ }
234
+ else {
235
+ geometry = new Point([0, 0]);
236
+ }
237
+ const olFeature = new Feature({
238
+ geometry,
239
+ ...feature.properties,
240
+ });
241
+ olFeature.setId(feature.id);
242
+ return olFeature;
243
+ });
244
+ source.addFeatures(olFeatures);
245
+ }
246
+ // Default style for all geometry types (points, lines, polygons)
247
+ const defaultStyle = new Style({
248
+ fill: new Fill({ color: 'rgba(25, 118, 210, 0.3)' }),
249
+ stroke: new Stroke({ color: '#1976d2', width: 2 }),
250
+ image: new Circle$1({
251
+ radius: 8,
252
+ fill: new Fill({ color: '#1976d2' }),
253
+ stroke: new Stroke({ color: '#d32f2f', width: 2 }),
254
+ }),
255
+ });
53
256
  const layer = new VectorLayer({
54
- source: new VectorSource(),
257
+ source,
55
258
  visible: config.visible ?? true,
56
259
  opacity: config.opacity ?? 1,
57
260
  zIndex: config.zIndex,
261
+ style: defaultStyle,
58
262
  });
59
263
  layer.set('id', config.id);
60
264
  map.addLayer(layer);
61
265
  this.layerCache.set(config.id, layer);
266
+ this.updateLayerState();
62
267
  return { id: config.id };
63
268
  }
64
269
  createTileLayer(config, map) {
@@ -89,10 +294,20 @@ class OlLayerService {
89
294
  layer.set('id', config.id);
90
295
  map.addLayer(layer);
91
296
  this.layerCache.set(config.id, layer);
297
+ this.updateLayerState();
92
298
  return { id: config.id };
93
299
  }
94
300
  createImageLayer(config, map) {
95
- const source = new ImageWMS({ url: config.source.url, params: config.source.params });
301
+ let source;
302
+ if (config.source.type === 'static') {
303
+ source = new ImageStatic({
304
+ url: config.source.url,
305
+ imageExtent: config.source.imageExtent ?? [0, 0, 1, 1],
306
+ });
307
+ }
308
+ else {
309
+ source = new ImageWMS({ url: config.source.url, params: config.source.params });
310
+ }
96
311
  const layer = new ImageLayer({
97
312
  source,
98
313
  visible: config.visible ?? true,
@@ -102,6 +317,7 @@ class OlLayerService {
102
317
  layer.set('id', config.id);
103
318
  map.addLayer(layer);
104
319
  this.layerCache.set(config.id, layer);
320
+ this.updateLayerState();
105
321
  return { id: config.id };
106
322
  }
107
323
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlLayerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -114,25 +330,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
114
330
  // OlVectorLayerComponent
115
331
  class OlVectorLayerComponent {
116
332
  layerService = inject(OlLayerService);
333
+ destroyRef = inject(DestroyRef);
117
334
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
118
335
  features = input([], ...(ngDevMode ? [{ debugName: "features" }] : /* istanbul ignore next */ []));
119
336
  zIndex = input(0, ...(ngDevMode ? [{ debugName: "zIndex" }] : /* istanbul ignore next */ []));
120
337
  opacity = input(1, ...(ngDevMode ? [{ debugName: "opacity" }] : /* istanbul ignore next */ []));
121
338
  visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
122
339
  style = input(...(ngDevMode ? [undefined, { debugName: "style" }] : /* istanbul ignore next */ []));
123
- ngOnInit() {
124
- this.layerService.addLayer({
125
- id: this.id(),
126
- type: 'vector',
127
- features: this.features(),
128
- zIndex: this.zIndex(),
129
- opacity: this.opacity(),
130
- visible: this.visible(),
131
- style: this.style(),
340
+ constructor() {
341
+ // Initialize layer after DOM is ready
342
+ afterNextRender(() => {
343
+ this.layerService.addLayer({
344
+ id: this.id(),
345
+ type: 'vector',
346
+ features: this.features(),
347
+ zIndex: this.zIndex(),
348
+ opacity: this.opacity(),
349
+ visible: this.visible(),
350
+ style: this.style(),
351
+ });
352
+ });
353
+ // Effect to sync features when input changes
354
+ effect(() => {
355
+ const currentFeatures = this.features();
356
+ // Only update if layer already exists (afterNextRender already created it)
357
+ if (this.layerService.getLayer(this.id())) {
358
+ this.layerService.updateFeatures(this.id(), currentFeatures);
359
+ }
360
+ });
361
+ // Cleanup when component is destroyed
362
+ this.destroyRef.onDestroy(() => {
363
+ this.layerService.removeLayer(this.id());
132
364
  });
133
- }
134
- ngOnDestroy() {
135
- this.layerService.removeLayer(this.id());
136
365
  }
137
366
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlVectorLayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
138
367
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: OlVectorLayerComponent, isStandalone: true, selector: "ol-vector-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, features: { classPropertyName: "features", publicName: "features", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -144,11 +373,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
144
373
  template: '',
145
374
  changeDetection: ChangeDetectionStrategy.OnPush,
146
375
  }]
147
- }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], features: [{ type: i0.Input, args: [{ isSignal: true, alias: "features", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }] } });
376
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], features: [{ type: i0.Input, args: [{ isSignal: true, alias: "features", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }] } });
148
377
 
149
378
  // OlTileLayerComponent
150
379
  class OlTileLayerComponent {
151
380
  layerService = inject(OlLayerService);
381
+ destroyRef = inject(DestroyRef);
152
382
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
153
383
  source = input.required(...(ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []));
154
384
  url = input(...(ngDevMode ? [undefined, { debugName: "url" }] : /* istanbul ignore next */ []));
@@ -157,34 +387,27 @@ class OlTileLayerComponent {
157
387
  zIndex = input(0, ...(ngDevMode ? [{ debugName: "zIndex" }] : /* istanbul ignore next */ []));
158
388
  opacity = input(1, ...(ngDevMode ? [{ debugName: "opacity" }] : /* istanbul ignore next */ []));
159
389
  visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
160
- ngOnInit() {
161
- // Retry adding layer if map is not ready yet
162
- this.tryAddLayer();
163
- }
164
- tryAddLayer(retryCount = 0) {
165
- const result = this.layerService.addLayer({
166
- id: this.id(),
167
- type: 'tile',
168
- source: {
169
- type: this.source(),
170
- url: this.url(),
171
- attributions: this.attributions(),
172
- params: this.params(),
173
- },
174
- zIndex: this.zIndex(),
175
- opacity: this.opacity(),
176
- visible: this.visible(),
390
+ constructor() {
391
+ // Initialize layer after DOM is ready
392
+ afterNextRender(() => {
393
+ this.layerService.addLayer({
394
+ id: this.id(),
395
+ type: 'tile',
396
+ source: {
397
+ type: this.source(),
398
+ url: this.url(),
399
+ attributions: this.attributions(),
400
+ params: this.params(),
401
+ },
402
+ zIndex: this.zIndex(),
403
+ opacity: this.opacity(),
404
+ visible: this.visible(),
405
+ });
406
+ });
407
+ // Cleanup when component is destroyed
408
+ this.destroyRef.onDestroy(() => {
409
+ this.layerService.removeLayer(this.id());
177
410
  });
178
- // If layer wasn't added (map not ready), retry with exponential backoff
179
- if (retryCount < 10) {
180
- setTimeout(() => {
181
- // Check if layer was actually added by trying again
182
- this.tryAddLayer(retryCount + 1);
183
- }, Math.min(50 * (retryCount + 1), 500));
184
- }
185
- }
186
- ngOnDestroy() {
187
- this.layerService.removeLayer(this.id());
188
411
  }
189
412
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlTileLayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
190
413
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: OlTileLayerComponent, isStandalone: true, selector: "ol-tile-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: true, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, attributions: { classPropertyName: "attributions", publicName: "attributions", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -196,7 +419,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
196
419
  template: '',
197
420
  changeDetection: ChangeDetectionStrategy.OnPush,
198
421
  }]
199
- }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], attributions: [{ type: i0.Input, args: [{ isSignal: true, alias: "attributions", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }] } });
422
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], attributions: [{ type: i0.Input, args: [{ isSignal: true, alias: "attributions", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }] } });
423
+
424
+ // OlImageLayerComponent
425
+ class OlImageLayerComponent {
426
+ layerService = inject(OlLayerService);
427
+ destroyRef = inject(DestroyRef);
428
+ id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
429
+ sourceType = input.required(...(ngDevMode ? [{ debugName: "sourceType" }] : /* istanbul ignore next */ []));
430
+ url = input.required(...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
431
+ params = input(...(ngDevMode ? [undefined, { debugName: "params" }] : /* istanbul ignore next */ []));
432
+ imageExtent = input(...(ngDevMode ? [undefined, { debugName: "imageExtent" }] : /* istanbul ignore next */ []));
433
+ zIndex = input(0, ...(ngDevMode ? [{ debugName: "zIndex" }] : /* istanbul ignore next */ []));
434
+ opacity = input(1, ...(ngDevMode ? [{ debugName: "opacity" }] : /* istanbul ignore next */ []));
435
+ visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
436
+ constructor() {
437
+ // Initialize layer after DOM is ready
438
+ afterNextRender(() => {
439
+ this.layerService.addLayer({
440
+ id: this.id(),
441
+ type: 'image',
442
+ source: {
443
+ type: this.sourceType(),
444
+ url: this.url(),
445
+ params: this.params(),
446
+ imageExtent: this.imageExtent(),
447
+ },
448
+ zIndex: this.zIndex(),
449
+ opacity: this.opacity(),
450
+ visible: this.visible(),
451
+ });
452
+ });
453
+ // Cleanup when component is destroyed
454
+ this.destroyRef.onDestroy(() => {
455
+ this.layerService.removeLayer(this.id());
456
+ });
457
+ }
458
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlImageLayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
459
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: OlImageLayerComponent, isStandalone: true, selector: "ol-image-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, sourceType: { classPropertyName: "sourceType", publicName: "sourceType", isSignal: true, isRequired: true, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: true, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, imageExtent: { classPropertyName: "imageExtent", publicName: "imageExtent", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
460
+ }
461
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlImageLayerComponent, decorators: [{
462
+ type: Component,
463
+ args: [{
464
+ selector: 'ol-image-layer',
465
+ template: '',
466
+ changeDetection: ChangeDetectionStrategy.OnPush,
467
+ }]
468
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], sourceType: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceType", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: true }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], imageExtent: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageExtent", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }] } });
200
469
 
201
470
  // Provider functions
202
471
  function withLayers() {
@@ -212,4 +481,4 @@ function provideLayers() {
212
481
  * Generated bundle index. Do not edit.
213
482
  */
214
483
 
215
- export { OlLayerService, OlTileLayerComponent, OlVectorLayerComponent, provideLayers, withLayers };
484
+ export { OlImageLayerComponent, OlLayerService, OlTileLayerComponent, OlVectorLayerComponent, provideLayers, withLayers };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-helpers/openlayers",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Modern Angular wrapper for OpenLayers with modular architecture, standalone components, and hybrid template/programmatic API",
5
5
  "homepage": "https://gaspar1992.github.io/angular-helpers/docs/openlayers",
6
6
  "repository": {
@@ -74,6 +74,7 @@
74
74
  "default": "./fesm2022/angular-helpers-openlayers-overlays.mjs"
75
75
  }
76
76
  },
77
+ "type": "module",
77
78
  "dependencies": {
78
79
  "tslib": "^2.3.0"
79
80
  }