@regionerne/gis-komponent 0.0.19 → 0.0.23

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,8 +1,8 @@
1
- import * as i1 from '@angular/common';
1
+ import * as i1$3 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { InjectionToken, inject, Injectable, Component, Input, ViewChild } from '@angular/core';
5
- import * as i2 from '@angular/material/icon';
4
+ import { InjectionToken, inject, Injectable, Component, Input, ViewChild, Inject } from '@angular/core';
5
+ import * as i3 from '@angular/material/icon';
6
6
  import { MatIconModule } from '@angular/material/icon';
7
7
  import Map$1 from 'ol/Map';
8
8
  import View from 'ol/View';
@@ -12,9 +12,9 @@ import WMTSCapabilities from 'ol/format/WMTSCapabilities';
12
12
  import ImageLayer from 'ol/layer/Image';
13
13
  import { HttpClient, HttpErrorResponse, HttpHeaders, provideHttpClient, withInterceptors } from '@angular/common/http';
14
14
  import OLLayerGroup from 'ol/layer/Group';
15
- import * as i5 from '@angular/material/select';
15
+ import * as i5$1 from '@angular/material/select';
16
16
  import { MatSelectModule } from '@angular/material/select';
17
- import * as i3$2 from '@angular/material/list';
17
+ import * as i3$1 from '@angular/material/list';
18
18
  import { MatListModule } from '@angular/material/list';
19
19
  import ol_control_mouse from 'ol/control/MousePosition';
20
20
  import ol_control_scale from 'ol/control/ScaleLine';
@@ -22,49 +22,59 @@ import { register } from 'ol/proj/proj4';
22
22
  import proj4 from 'proj4';
23
23
  import { Control, Rotate } from 'ol/control';
24
24
  import { Vector, TileWMS } from 'ol/source';
25
- import { BehaviorSubject, Subject, of, tap, map, ReplaySubject, filter, combineLatest, catchError, throwError } from 'rxjs';
25
+ import { Subject, BehaviorSubject, tap, switchMap, EMPTY, of, map, ReplaySubject, filter, combineLatest, Observable, takeUntil, take, mergeWith, debounceTime, distinctUntilChanged, forkJoin, catchError, throwError } from 'rxjs';
26
26
  import WMTS, { optionsFromCapabilities } from 'ol/source/WMTS';
27
+ import VectorLayer from 'ol/layer/Vector';
28
+ import TileSource from 'ol/source/Tile';
29
+ import ImageSource from 'ol/source/Image';
30
+ import VectorSource from 'ol/source/Vector';
31
+ import { unByKey } from 'ol/Observable';
32
+ import { MAT_SNACK_BAR_DATA, MatSnackBarRef, MatSnackBar } from '@angular/material/snack-bar';
27
33
  import * as i4 from '@angular/cdk/drag-drop';
28
34
  import { moveItemInArray, transferArrayItem, DragDropModule } from '@angular/cdk/drag-drop';
29
- import * as i3 from '@angular/material/form-field';
35
+ import * as i1 from '@angular/material/form-field';
30
36
  import { MatFormFieldModule } from '@angular/material/form-field';
31
- import * as i2$1 from '@angular/forms';
37
+ import * as i1$1 from '@angular/forms';
32
38
  import { FormsModule } from '@angular/forms';
33
- import * as i3$1 from '@angular/material/expansion';
39
+ import * as i5 from '@angular/material/expansion';
34
40
  import { MatExpansionModule } from '@angular/material/expansion';
35
41
  import * as i6 from '@angular/material/input';
36
42
  import { MatInputModule } from '@angular/material/input';
37
43
  import ol_control_Control from 'ol/control/Control';
38
- import VectorLayer from 'ol/layer/Vector';
39
- import TileSource from 'ol/source/Tile';
40
- import ImageSource from 'ol/source/Image';
41
- import VectorSource from 'ol/source/Vector';
42
- import { unByKey } from 'ol/Observable';
43
- import { MAT_SNACK_BAR_DATA, MatSnackBarRef, MatSnackBar } from '@angular/material/snack-bar';
44
+ import * as i7 from '@angular/material/tooltip';
45
+ import { MatTooltipModule } from '@angular/material/tooltip';
44
46
  import 'ol/ol.css';
45
47
  import { LineString, Point } from 'ol/geom';
46
48
  import { getArea, getLength } from 'ol/sphere';
47
- import Draw from 'ol/interaction/Draw';
49
+ import Draw, { createBox, createRegularPolygon } from 'ol/interaction/Draw';
48
50
  import { Snap, Select as Select$1, Modify } from 'ol/interaction';
49
- import { Style, Circle, Stroke, Fill, Text } from 'ol/style';
51
+ import { Style, Circle, Stroke, Fill, Text, RegularShape } from 'ol/style';
50
52
  import * as i4$1 from '@angular/material/core';
51
53
  import { MatOptionModule } from '@angular/material/core';
52
54
  import * as SLDReader from '@nieuwlandgeo/sldreader';
53
55
  import WKT from 'ol/format/WKT';
54
- import { extend, createEmpty, buffer as buffer$1 } from 'ol/extent';
55
56
  import Feature$1 from 'ol/Feature';
56
57
  import { never, always } from 'ol/events/condition';
57
- import { buffer, featureCollection, difference, booleanIntersects, union } from '@turf/turf';
58
+ import { buffer, featureCollection, difference, booleanIntersects, union, point, booleanPointInPolygon, area } from '@turf/turf';
58
59
  import GeoJSON from 'ol/format/GeoJSON';
59
- import * as i7 from '@angular/material/tooltip';
60
- import { MatTooltipModule } from '@angular/material/tooltip';
61
60
  import * as i8 from '@angular/material/slide-toggle';
62
61
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
63
62
  import { Feature } from 'ol';
63
+ import { extend, createEmpty, buffer as buffer$1 } from 'ol/extent';
64
64
  import Select from 'ol/interaction/Select';
65
65
  import html2canvas from 'html2canvas-pro';
66
- import * as i5$1 from '@angular/material/autocomplete';
66
+ import CircleStyle from 'ol/style/Circle';
67
+ import { transform } from 'ol/proj';
68
+ import * as i2 from '@angular/material/button';
69
+ import { MatButtonModule } from '@angular/material/button';
70
+ import * as i1$2 from '@angular/material/dialog';
71
+ import { MAT_DIALOG_DATA, MatDialogModule, MatDialogTitle, MatDialogContent, MatDialogActions } from '@angular/material/dialog';
72
+ import * as i5$2 from '@angular/material/autocomplete';
67
73
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
74
+ import WFS from 'ol/format/WFS';
75
+ import { like } from 'ol/format/filter';
76
+ import { map as map$1 } from 'rxjs/operators';
77
+ import { createStringXY } from 'ol/coordinate';
68
78
 
69
79
  const GISKOMPONENT_CONFIG = new InjectionToken('GisKomponentConfig');
70
80
 
@@ -116,83 +126,6 @@ class CopyrightControl extends Control {
116
126
  }
117
127
  }
118
128
 
119
- class LayerHelperService {
120
- activeLayersChanged = new BehaviorSubject(true);
121
- _layerDbIdKey = 'layerDbId';
122
- _layerGroupDbIdKey = 'layerGroupDbId';
123
- _layerIdsToDisplayInMapKeyName = 'layerIdsToDisplayInMap';
124
- setDbId(layer, id) {
125
- layer.set(this._layerDbIdKey, id);
126
- }
127
- getDbId(layer) {
128
- const dbId = layer.get(this._layerDbIdKey) ?? -1;
129
- return +dbId;
130
- }
131
- setLayerGroupDbId(layer, id) {
132
- layer.set(this._layerGroupDbIdKey, id);
133
- }
134
- getLayerGroupDbId(layer) {
135
- const dbId = layer.get(this._layerGroupDbIdKey) ?? -1;
136
- return +dbId;
137
- }
138
- applyCachedLayersToDisplayInMap(map, profileId) {
139
- this.activeLayersChanged.next(true);
140
- const layerIdsCachedToDisplay = localStorage.getItem(`${this._layerIdsToDisplayInMapKeyName}_${profileId}`)?.split(',');
141
- if (layerIdsCachedToDisplay) {
142
- //Bottom layers are rendered first, top layers are rendered last (on top)
143
- layerIdsCachedToDisplay.reverse();
144
- map.getLayers().getArray().forEach(layergroup => {
145
- if (layergroup instanceof OLLayerGroup) {
146
- layergroup.getLayers().getArray().forEach(l => {
147
- if (!layerIdsCachedToDisplay.some(id => l.get(this._layerDbIdKey) == id)) {
148
- const current = l.getVisible();
149
- if (current) {
150
- l.setVisible(!current);
151
- }
152
- }
153
- else {
154
- //Set z index to match the order in cache
155
- l.setZIndex(layerIdsCachedToDisplay.indexOf(l.get(this._layerDbIdKey).toString()));
156
- //console.log('layer id '+l.get(this._layerDbIdKey)+' - setZIndex:'+layerIdsCachedToDisplay.indexOf(l.get(this._layerDbIdKey).toString()));
157
- }
158
- });
159
- }
160
- });
161
- }
162
- }
163
- updateLayerOpacityInMap(map, layer) {
164
- map.getLayers().getArray().forEach(layergroup => {
165
- if (layergroup instanceof OLLayerGroup) {
166
- layergroup.getLayers().getArray().forEach(l => {
167
- if (l.get(this._layerDbIdKey) === layer.id && layer.opacity) {
168
- l.setOpacity(layer.opacity);
169
- }
170
- });
171
- }
172
- });
173
- }
174
- toggleLayerInMap(map, layer) {
175
- map.getLayers().getArray().forEach(layergroup => {
176
- if (layergroup instanceof OLLayerGroup) {
177
- layergroup.getLayers().getArray().forEach(l => {
178
- if (l.get(this._layerDbIdKey) === layer.id) {
179
- const current = l.getVisible();
180
- l.setVisible(!current);
181
- }
182
- });
183
- }
184
- });
185
- }
186
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerHelperService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
187
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerHelperService, providedIn: 'root' });
188
- }
189
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerHelperService, decorators: [{
190
- type: Injectable,
191
- args: [{
192
- providedIn: 'root'
193
- }]
194
- }] });
195
-
196
129
  class LibNotificationComponent {
197
130
  data = inject(MAT_SNACK_BAR_DATA);
198
131
  _snackRef = inject((MatSnackBarRef));
@@ -257,6 +190,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
257
190
 
258
191
  class LayerErrorService {
259
192
  layerStatusChanged = new Subject();
193
+ layerErrored = new Subject();
260
194
  layerStatuses = new Map();
261
195
  listeners = new Map();
262
196
  _errorService = inject(LibErrorService);
@@ -275,6 +209,7 @@ class LayerErrorService {
275
209
  console.error(`[Layer ${layerId}] load error:`, event);
276
210
  this._errorService.show(new Error(`Indlæsningsfejl for lag med id ${layerId}.`));
277
211
  this.layerStatusChanged.next(layerId);
212
+ this.layerErrored.next(layerId);
278
213
  };
279
214
  const clearError = () => {
280
215
  this.layerStatuses.set(layerId, { layerId, hasError: false });
@@ -324,6 +259,121 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
324
259
  args: [{ providedIn: 'root' }]
325
260
  }] });
326
261
 
262
+ class LayerHelperService {
263
+ activeLayersChanged = new BehaviorSubject(true);
264
+ _layerDbIdKey = 'layerDbId';
265
+ _layerGroupDbIdKey = 'layerGroupDbId';
266
+ _mapFilteredLayerGroupsKeyName = 'mapFilteredLayerGroups';
267
+ _layerErrorService = inject(LayerErrorService);
268
+ layerActivatedByBackgroundGroup = new Subject();
269
+ setDbId(layer, id) {
270
+ layer.set(this._layerDbIdKey, id);
271
+ }
272
+ getDbId(layer) {
273
+ const dbId = layer.get(this._layerDbIdKey) ?? -1;
274
+ return +dbId;
275
+ }
276
+ setLayerGroupDbId(layer, id) {
277
+ layer.set(this._layerGroupDbIdKey, id);
278
+ }
279
+ getLayerGroupDbId(layer) {
280
+ const dbId = layer.get(this._layerGroupDbIdKey) ?? -1;
281
+ return +dbId;
282
+ }
283
+ applyCachedLayersToDisplayInMap(map, profileId) {
284
+ this.activeLayersChanged.next(true);
285
+ const cacheValue = localStorage.getItem(`${this._mapFilteredLayerGroupsKeyName}_${profileId}`);
286
+ if (cacheValue) {
287
+ const layersCachedToDisplay = JSON.parse(cacheValue).cachedLayerGroups
288
+ .flatMap((lg) => lg.layers)
289
+ .map((l) => ({ id: l.id, visible: l.visible }));
290
+ //Bottom layers are rendered first, top layers are rendered last (on top)
291
+ layersCachedToDisplay.reverse();
292
+ map.getLayers().getArray().forEach(layergroup => {
293
+ if (layergroup instanceof OLLayerGroup) {
294
+ layergroup.getLayers().getArray().forEach(l => {
295
+ const cachedLayer = layersCachedToDisplay
296
+ .find((layer) => l.get(this._layerDbIdKey) == layer.id);
297
+ const current = l.getVisible();
298
+ if (cachedLayer != undefined && current != cachedLayer.visible) {
299
+ l.setVisible(cachedLayer.visible);
300
+ }
301
+ //Set z index to match the order in cache
302
+ l.setZIndex(layersCachedToDisplay.indexOf(cachedLayer));
303
+ //console.log('layer id '+l.get(this._layerDbIdKey)+' - setZIndex:'+layerIdsCachedToDisplay.indexOf(l.get(this._layerDbIdKey).toString()))
304
+ });
305
+ }
306
+ });
307
+ }
308
+ }
309
+ startFailoverForBackgroundGroup(aMap, groupId) {
310
+ const currentIndex$ = new BehaviorSubject(0);
311
+ const layergroup = aMap.getLayers().getArray()
312
+ .find(layergroup => layergroup instanceof OLLayerGroup && layergroup.get('id') === groupId);
313
+ const items = layergroup.getLayers().getArray().sort((a, b) => (b.getZIndex() ?? 0) - (a.getZIndex() ?? 0));
314
+ // Handles activating the current item
315
+ const activation$ = currentIndex$.pipe(tap(index => {
316
+ // deactivate all first
317
+ items.forEach(layer => layer.setVisible(false));
318
+ // if out of range, stop completely
319
+ if (index >= items.length) {
320
+ console.warn('No more items left. Stopping failover.');
321
+ return;
322
+ }
323
+ // activate current
324
+ const layer = items[index];
325
+ console.log('Failover turning layer on:', layer.get(this._layerDbIdKey));
326
+ layer.setVisible(true);
327
+ this.layerActivatedByBackgroundGroup.next(layer.get(this._layerDbIdKey));
328
+ }),
329
+ // Listen for failures only while we have a valid index
330
+ switchMap(index => {
331
+ if (index >= items.length)
332
+ return EMPTY;
333
+ const currentItem = items[index];
334
+ return this._layerErrorService.layerErrored.pipe(tap(failedId => {
335
+ // If the current one failed, move to next
336
+ if (failedId === currentItem.get(this._layerDbIdKey)) {
337
+ console.log('Failover layer failed:', currentItem.get(this._layerDbIdKey));
338
+ currentIndex$.next(index + 1);
339
+ }
340
+ }));
341
+ }));
342
+ activation$.subscribe();
343
+ }
344
+ updateLayerOpacityInMap(map, layer) {
345
+ map.getLayers().getArray().forEach(layergroup => {
346
+ if (layergroup instanceof OLLayerGroup) {
347
+ layergroup.getLayers().getArray().forEach(l => {
348
+ if (l.get(this._layerDbIdKey) === layer.id && layer.opacity) {
349
+ l.setOpacity(layer.opacity);
350
+ }
351
+ });
352
+ }
353
+ });
354
+ }
355
+ toggleLayerInMap(map, layerId) {
356
+ map.getLayers().getArray().forEach(layergroup => {
357
+ if (layergroup instanceof OLLayerGroup) {
358
+ layergroup.getLayers().getArray().forEach(l => {
359
+ if (l.get(this._layerDbIdKey) === layerId) {
360
+ const current = l.getVisible();
361
+ l.setVisible(!current);
362
+ }
363
+ });
364
+ }
365
+ });
366
+ }
367
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerHelperService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
368
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerHelperService, providedIn: 'root' });
369
+ }
370
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerHelperService, decorators: [{
371
+ type: Injectable,
372
+ args: [{
373
+ providedIn: 'root'
374
+ }]
375
+ }] });
376
+
327
377
  class LayerSelectorComponent {
328
378
  set contentIcon(content) {
329
379
  this._layerSelectorIcon = content;
@@ -340,17 +390,17 @@ class LayerSelectorComponent {
340
390
  showLegend = false; // TO DO - this will be added later, as a change (probably as a Profile setting)
341
391
  showSelector = false;
342
392
  legendUrl = 'https://docs.geoserver.org/main/en/user/_images/samplelegend.png'; // TO DO - remove this (mockup for now, will be done as a change later)
343
- _namesToGoLast = ['Baggrundskort'];
344
393
  _layerSelectorIcon;
345
394
  _layerSelectorIconControl;
346
395
  _layerSelectorBody;
347
396
  _layerSelectorBodyControl;
348
397
  _mapFilteredLayerGroupsKeyName = 'mapFilteredLayerGroups';
349
- _layerIdsToDisplayInMapKeyName = 'layerIdsToDisplayInMap';
350
398
  _layerHelper = inject(LayerHelperService);
351
399
  _layerErrorService = inject(LayerErrorService);
352
400
  ngOnInit() {
353
- this._layerErrorService.layerStatusChanged
401
+ this._layerHelper.layerActivatedByBackgroundGroup
402
+ .subscribe(layerId => this.toggleLayer(layerId, undefined, true));
403
+ this._layerErrorService.layerErrored
354
404
  .subscribe(layerId => {
355
405
  const layerHasErrors = this._layerErrorService.getLayerStatus(layerId)?.hasError;
356
406
  if (layerHasErrors != undefined)
@@ -384,16 +434,25 @@ class LayerSelectorComponent {
384
434
  this.filteredLayerGroups = this.setfilteredGroups();
385
435
  this._cacheProfileInfo();
386
436
  }
437
+ // Apply Failover logic to all background groups
438
+ this.filteredLayerGroups.filter(group => group.background)
439
+ .forEach(group => {
440
+ group.layers.forEach(layer => layer.visible = false); //Turn all layers off in selector to begin with
441
+ group.visible = true; // Expand the group (there will be at least one active layer)
442
+ group.expanded = true;
443
+ this._layerHelper.startFailoverForBackgroundGroup(this.map, group.id);
444
+ });
387
445
  this._initializeMapIconControl();
388
446
  }
389
447
  }
390
- toggleLayer(event, layer) {
391
- event.stopPropagation(); // Prevent the panel from expanding/collapsing
392
- this._layerHelper.toggleLayerInMap(this.map, layer);
448
+ toggleLayer(layerId, event, skipMapToggle = false) {
449
+ event?.stopPropagation(); // Prevent the panel from expanding/collapsing
450
+ if (!skipMapToggle)
451
+ this._layerHelper.toggleLayerInMap(this.map, layerId);
393
452
  // Toggle layer in all groups in the selector UI
394
453
  this.filteredLayerGroups.forEach(group => {
395
454
  group.layers.forEach(l => {
396
- if (layer.id === l.id) {
455
+ if (layerId === l.id) {
397
456
  l.visible = !l.visible;
398
457
  }
399
458
  });
@@ -415,23 +474,30 @@ class LayerSelectorComponent {
415
474
  toggleGroup(event, layerGroup) {
416
475
  event.stopPropagation(); // Prevent the panel from expanding/collapsing
417
476
  const visible = !layerGroup.visible;
418
- layerGroup.layers.forEach(layer => {
419
- if (layer.visible != visible) {
420
- //Toggle layer in map
421
- this._layerHelper.toggleLayerInMap(this.map, layer);
422
- // Toggle layer in all groups in the selector UI
423
- this.filteredLayerGroups.forEach(group => {
424
- group.layers.forEach(l => {
425
- if (layer.id === l.id) {
426
- l.visible = !l.visible;
427
- }
477
+ if (visible && layerGroup.background) {
478
+ //Toggle background group on, apply failover logic
479
+ layerGroup.layers.forEach(layer => layer.visible = false); // Turn all off in selector to begin with
480
+ this._layerHelper.startFailoverForBackgroundGroup(this.map, layerGroup.id);
481
+ }
482
+ else {
483
+ layerGroup.layers.forEach(layer => {
484
+ if (layer.visible != visible) {
485
+ //Toggle layer in map
486
+ this._layerHelper.toggleLayerInMap(this.map, layer.id);
487
+ // Toggle layer in all groups in the selector UI
488
+ this.filteredLayerGroups.forEach(group => {
489
+ group.layers.forEach(l => {
490
+ if (layer.id === l.id) {
491
+ l.visible = !l.visible;
492
+ }
493
+ });
494
+ group.noOfVisibleLayers = group.layers.filter(l => l.visible).length;
495
+ group.visible = group.layers.some(l => l.visible);
496
+ group.expanded = group.layers.some(l => l.visible);
428
497
  });
429
- group.noOfVisibleLayers = group.layers.filter(l => l.visible).length;
430
- group.visible = group.layers.some(l => l.visible);
431
- group.expanded = group.layers.some(l => l.visible);
432
- });
433
- }
434
- });
498
+ }
499
+ });
500
+ }
435
501
  layerGroup.visible = visible;
436
502
  layerGroup.expanded = layerGroup.layers.some(l => l.visible);
437
503
  this._cacheProfileInfo();
@@ -470,11 +536,9 @@ class LayerSelectorComponent {
470
536
  })
471
537
  .filter(g => g.layers.length > 0)
472
538
  .sort((a, b) => {
473
- const aIsLast = this._namesToGoLast.includes(a.name) || a.layers.some(layer => layer.background);
474
- const bIsLast = this._namesToGoLast.includes(b.name) || b.layers.some(layer => layer.background);
475
- if (aIsLast && !bIsLast)
539
+ if (a.background && !b.background)
476
540
  return 1;
477
- if (!aIsLast && bIsLast)
541
+ if (!a.background && b.background)
478
542
  return -1;
479
543
  return a.sortOrder - b.sortOrder;
480
544
  });
@@ -508,18 +572,16 @@ class LayerSelectorComponent {
508
572
  _cacheProfileInfo() {
509
573
  const cacheItem = { profile: this.profile, cachedLayerGroups: this.filteredLayerGroups };
510
574
  localStorage.setItem(`${this._mapFilteredLayerGroupsKeyName}_${this.profile.id}`, JSON.stringify(cacheItem));
511
- localStorage.setItem(`${this._layerIdsToDisplayInMapKeyName}_${this.profile.id}`, this.filteredLayerGroups
512
- .flatMap(lg => lg.layers)
513
- .filter(lg => lg.visible)
514
- .map(lg => lg.id).join(','));
515
575
  // Reflect new order in map
516
576
  this._layerHelper.applyCachedLayersToDisplayInMap(this.map, this.profile.id);
517
577
  }
518
578
  _initializeMapIconControl() {
519
579
  this.map.removeControl(this._layerSelectorIconControl);
520
- const element = this._layerSelectorIcon.nativeElement;
521
- this._layerSelectorIconControl = new ol_control_Control({ element: element });
522
- this.map.addControl(this._layerSelectorIconControl);
580
+ if (this._layerSelectorIcon?.nativeElement) {
581
+ const element = this._layerSelectorIcon.nativeElement;
582
+ this._layerSelectorIconControl = new ol_control_Control({ element: element });
583
+ this.map.addControl(this._layerSelectorIconControl);
584
+ }
523
585
  }
524
586
  _addMapBodyControl() {
525
587
  this.map.removeControl(this._layerSelectorBodyControl);
@@ -537,12 +599,12 @@ class LayerSelectorComponent {
537
599
  }));
538
600
  }
539
601
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
540
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: LayerSelectorComponent, isStandalone: true, selector: "lib-layer-selector", inputs: { map: "map", profile: "profile", currentZoomLevel: "currentZoomLevel" }, viewQueries: [{ propertyName: "contentIcon", first: true, predicate: ["layerSelectorIcon"], descendants: true }, { propertyName: "contentBody", first: true, predicate: ["layerSelectorBody"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #layerSelectorIcon id=\"layerSelector\" class=\"ol-unselectable ol-control layer-selector-icon\">\n <mat-icon (click)=\"toggleLayerSelector()\">layers</mat-icon>\n</div>\n<div #layerSelectorBody [class.display-none]=\"!showSelector\" class=\"layer-selector-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"ol-unselectable ol-control layer-selector-body\">\n <div class=\"search-section\">\n <mat-form-field appearance=\"outline\" class=\"w-full\">\n <mat-label>Filtrer</mat-label>\n <input \n matInput \n type=\"text\" \n [(ngModel)]=\"searchText\" \n (ngModelChange)=\"filteredLayerGroups=setfilteredGroups()\"\n placeholder=\"Skriv for at filtrere...\"\n />\n </mat-form-field>\n <mat-icon (click)=\"clearSearchText()\">undo</mat-icon>\n </div>\n \n <div\n cdkDropList\n [cdkDropListData]=\"filteredLayerGroups\"\n (cdkDropListDropped)=\"dropGroup($event)\"\n class=\"item-list\">\n @for (group of filteredLayerGroups; track group.id; let gIndex = $index) {\n <div class=\"group\" cdkDrag cdkDragPreviewDisabled>\n <mat-expansion-panel [(expanded)]=\"group.expanded\">\n <mat-expansion-panel-header>\n <mat-panel-title>\n @if (group.expanded) {\n <mat-icon>arrow_upward</mat-icon>\n }\n @if (!group.expanded) {\n <mat-icon>arrow_downward</mat-icon> \n }\n {{ group.name }} \n <mat-icon class=\"lightbulb\">lightbulb</mat-icon>\n ({{ group.noOfVisibleLayers }}/{{ group.layers.length }})\n @if (group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-on\">power</mat-icon>(t\u00E6nd)\n }\n @if (!group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-off\">power_off</mat-icon>(sluk)\n }\n </mat-panel-title>\n </mat-expansion-panel-header>\n <!-- This is only shown during drag -->\n <!-- <div *cdkDragPreview class=\"drag-preview\">\n {{ group.name }}\n </div> -->\n\n <!-- Placeholder to avoid jump -->\n <!-- <div *cdkDragPlaceholder class=\"drag-placeholder\"></div> -->\n\n <div\n cdkDropList\n [cdkDropListData]=\"group.layers\"\n (cdkDropListDropped)=\"dropLayer($event, group)\"\n class=\"item-list\">\n @for (layer of group.layers; track layer.id; let iIndex = $index) {\n <mat-expansion-panel expanded=\"true\" [disabled]=\"!showLegend\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" cdkDrag cdkDragPreviewDisabled>\n <mat-icon class=\"drag-indicator\">drag_indicator</mat-icon>\n <span>{{ layer.name }}</span>\n @if (layer.maxZoom < currentZoomLevel || layer.minZoom > currentZoomLevel) {\n <mat-icon class=\"zoom-off\">browser_not_supported</mat-icon>(zoom)\n }\n @if (layer.hasErrors) {\n <mat-icon class=\"zoom-off\">wifi_off</mat-icon>(fejle)\n }\n @if (layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-on\">power</mat-icon>(t\u00E6nd)\n }\n @if (!layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-off\">power_off</mat-icon>(sluk)\n }\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"layer.opacity\"\n (click)=\"stopDrag($event)\"\n (input)=\"updateOpacity(layer)\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @if (showLegend) {\n <img [src]=\"legendUrl\" class=\"legend-thumbnail\"/>\n }\n </mat-expansion-panel>\n }\n </div>\n </mat-expansion-panel>\n </div>\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .layer-selector-icon{position:absolute;left:auto;right:4em;bottom:.5em;z-index:1000}::ng-deep .layer-selector-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .layer-selector-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}.layer-selector-body-wrapper{position:absolute;left:auto;right:4em;bottom:4em;z-index:1000;cursor:grab}.layer-selector-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.layer-selector-body-wrapper .ol-control{border-radius:0}.drag-handle-selector{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 40%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab;box-shadow:0 -2px 8px #0003}.drag-handle-selector mat-icon{color:#fff;font-size:20px;width:20px;height:20px}::ng-deep .layer-selector-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 40%,transparent);box-shadow:0 4px 20px #00000026;width:480px;max-height:500px;overflow:hidden;display:flex;flex-direction:column}::ng-deep .layer-selector-body .search-section{display:flex;align-items:center;gap:6px;padding:8px 12px 6px}::ng-deep .layer-selector-body .search-section mat-form-field{flex:1}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-text-field-wrapper{padding-bottom:0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-wrapper{padding-bottom:0;margin-bottom:0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-infix{padding-bottom:6px;min-height:auto}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline{background:#fff}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline-thick{color:#1976d2}::ng-deep .layer-selector-body .search-section mat-form-field input{font-size:13px;padding:3px 0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-label{color:#fff;font-weight:500;font-size:13px}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-subscript-wrapper{height:0;margin-top:0}::ng-deep .layer-selector-body .search-section mat-icon{color:#fff;cursor:pointer;padding:6px;border-radius:4px;transition:all .2s ease;font-size:24px;width:24px;height:24px;display:flex;justify-content:center;align-items:center}::ng-deep .layer-selector-body .search-section mat-icon:hover{color:#f9fafb}::ng-deep .layer-selector-body .item-list{flex:1;overflow-y:auto;padding:6px;max-height:400px}::ng-deep .layer-selector-body .item-list .group{margin-bottom:6px;overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel{box-shadow:none!important;border-radius:0!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header{padding:0 12px;height:40px;background:color-mix(in srgb,#000 55%,transparent)}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header:hover{background:color-mix(in srgb,#000 60%,transparent)!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title{align-items:center;gap:6px;font-weight:600;color:#fff;font-size:13px}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon{color:#fff;font-size:16px;width:16px;height:16px;transition:transform .2s ease}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.lightbulb{color:#dfca0e}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-on{color:#4caf50}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-off{color:#f44336}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content{background:color-mix(in srgb,#000 40%,transparent)}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content .mat-expansion-panel-body{padding:4px 0}::ng-deep .layer-selector-body .item-list .group .item-list{padding:0;max-height:none}::ng-deep .layer-selector-body .item-list .group .item-list .item{display:flex;align-items:center;gap:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}::ng-deep .layer-selector-body .item-list .group .item-list .item:last-child{border-bottom:none}::ng-deep .layer-selector-body .item-list .group .item-list .item:hover{background-color:#0000004d;transition:all .2s ease}::ng-deep .layer-selector-body .item-list .group .item-list .item.cdk-drag-preview{background:#fff;box-shadow:0 4px 12px #00000026;border-radius:4px}::ng-deep .layer-selector-body .item-list .group .item-list .item.cdk-drag-placeholder{background:#e3f2fd;opacity:.6}::ng-deep .layer-selector-body .item-list .group .item-list .item.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon{flex-shrink:0}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.drag-indicator{color:#fff;font-size:16px;width:16px;height:16px;cursor:grab}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on{color:#4caf50;font-size:18px;width:18px;height:18px;cursor:pointer;margin-left:auto;padding:3px;border-radius:3px}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on:hover{background:#4caf5033}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.zoom-off{color:#f44336;font-size:16px;width:16px;height:16px}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off{color:#f44336;font-size:18px;width:18px;height:18px;cursor:pointer;margin-left:auto;padding:3px;border-radius:3px}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off:hover{background:#f4433633}::ng-deep .layer-selector-body .item-list .group .item-list .item>:nth-child(2){flex:1;font-size:13px;color:#fff;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .layer-selector-body .item-list .group .item-list .item input[type=range]{width:80px;height:4px;margin:0 4px;flex-shrink:0}::ng-deep .mat-expansion-indicator svg{fill:#fff!important}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 15px #00000026;background:#fff;padding:10px 12px}.cdk-drag-placeholder{opacity:.3}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.item-list.cdk-drop-list-dragging .item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.power-on{color:#4caf50}.power-off{color:#f44336}.display-none{display:none}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar{width:8px;border-radius:10px;border:5px solid transparent}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb{background:#0000004d;border:5px solid transparent;border-radius:10px;background-clip:padding-box}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb:hover{background:#0006;background-clip:padding-box;border:3px solid transparent}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
602
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: LayerSelectorComponent, isStandalone: true, selector: "lib-layer-selector", inputs: { map: "map", profile: "profile", currentZoomLevel: "currentZoomLevel" }, viewQueries: [{ propertyName: "contentIcon", first: true, predicate: ["layerSelectorIcon"], descendants: true }, { propertyName: "contentBody", first: true, predicate: ["layerSelectorBody"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #layerSelectorIcon id=\"layerSelector\" class=\"ol-unselectable ol-control layer-selector-icon\">\n <mat-icon (click)=\"toggleLayerSelector()\">layers</mat-icon>\n</div>\n<div #layerSelectorBody [class.display-none]=\"!showSelector\" class=\"layer-selector-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <div class=\"drag-handle-content\">\n <div class=\"drag-handle-icons\">\n <mat-icon class=\"drag-indicator-right\">open_with</mat-icon>\n <mat-icon class=\"minimize-button\" (click)=\"toggleLayerSelector()\">minimize</mat-icon>\n </div>\n </div>\n </div>\n <div class=\"ol-unselectable ol-control layer-selector-body\">\n <div class=\"search-section\">\n <mat-form-field appearance=\"outline\" class=\"w-full\">\n <mat-label>Filtrer</mat-label>\n <input \n matInput \n type=\"text\" \n [(ngModel)]=\"searchText\" \n (ngModelChange)=\"filteredLayerGroups=setfilteredGroups()\"\n placeholder=\"Skriv for at filtrere...\"\n />\n </mat-form-field>\n <mat-icon (click)=\"clearSearchText()\">undo</mat-icon>\n </div>\n \n <div\n cdkDropList\n [cdkDropListData]=\"filteredLayerGroups\"\n (cdkDropListDropped)=\"dropGroup($event)\"\n class=\"item-list\">\n @for (group of filteredLayerGroups; track group.id; let gIndex = $index) {\n <div class=\"group\" cdkDrag cdkDragPreviewDisabled>\n <mat-expansion-panel [(expanded)]=\"group.expanded\">\n <mat-expansion-panel-header>\n <mat-panel-title>\n @if (group.expanded) {\n <mat-icon>arrow_upward</mat-icon>\n }\n @if (!group.expanded) {\n <mat-icon>arrow_downward</mat-icon> \n }\n {{ group.name }} \n <mat-icon class=\"lightbulb\">lightbulb</mat-icon>\n ({{ group.noOfVisibleLayers }}/{{ group.layers.length }})\n @if (group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-on\" \n matTooltip=\"T\u00E6nd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon> \n }\n @if (!group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-off\"\n matTooltip=\"Sluk\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon>\n }\n </mat-panel-title>\n </mat-expansion-panel-header>\n <!-- This is only shown during drag -->\n <!-- <div *cdkDragPreview class=\"drag-preview\">\n {{ group.name }}\n </div> -->\n\n <!-- Placeholder to avoid jump -->\n <!-- <div *cdkDragPlaceholder class=\"drag-placeholder\"></div> -->\n\n <div\n cdkDropList\n [cdkDropListData]=\"group.layers\"\n (cdkDropListDropped)=\"dropLayer($event, group)\"\n class=\"item-list\">\n @for (layer of group.layers; track layer.id; let iIndex = $index) {\n <mat-expansion-panel expanded=\"false\" [disabled]=\"!layer.description\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" cdkDrag cdkDragPreviewDisabled>\n <div class=\"item-left\">\n <mat-icon class=\"drag-indicator\">drag_indicator</mat-icon>\n <span>{{ layer.name }}</span>\n </div>\n <div class=\"item-center\">\n @if (layer.maxZoom < currentZoomLevel || layer.minZoom > currentZoomLevel) {\n <mat-icon class=\"zoom-off\" \n matTooltip=\"Zoom\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">browser_not_supported\n </mat-icon>\n }\n @if (layer.hasErrors) {\n <mat-icon class=\"zoom-off\" \n matTooltip=\"Fejl\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">priority_high\n </mat-icon>\n\n }\n </div>\n <div class=\"item-right\">\n @if (layer.visible) {\n <mat-icon (click)=\"toggleLayer(layer.id, $event)\" class=\"power-on\" \n matTooltip=\"T\u00E6nd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon>\n }\n @if (!layer.visible) {\n <mat-icon (click)=\"toggleLayer(layer.id, $event)\" class=\"power-off\"\n matTooltip=\"Sluk\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon>\n }\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"layer.opacity\"\n (click)=\"stopDrag($event)\"\n (input)=\"updateOpacity(layer)\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n <div class=\"layer-description\">{{ layer.description }}</div>\n @if (showLegend) {\n <img [src]=\"legendUrl\" class=\"legend-thumbnail\"/>\n }\n </mat-expansion-panel>\n }\n </div>\n </mat-expansion-panel>\n </div>\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .layer-selector-icon{position:absolute;left:auto;right:1em;bottom:4.5em;z-index:1000}::ng-deep .layer-selector-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .layer-selector-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}.layer-selector-body-wrapper{position:absolute;left:auto;right:4em;bottom:.2em;z-index:1000;cursor:grab;max-width:calc(100vw - 8em)}.layer-selector-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.layer-selector-body-wrapper .ol-control{border-radius:0}@media (max-width: 767px){.layer-selector-body-wrapper{right:.5em;bottom:4em;max-width:calc(100vw - 7em);left:.5em;width:calc(100vw - 7em)}}@media (min-width: 768px) and (max-width: 1024px){.layer-selector-body-wrapper{right:3.5em;bottom:.5em;max-width:calc(100vw - 2em)}}.drag-handle-selector{display:flex;align-items:center;justify-content:flex-end;border-radius:5px 5px 0 0;padding:5px;cursor:grab;background:color-mix(in srgb,#000 60%,transparent)}.drag-handle-content{display:flex;align-items:center;justify-content:flex-end;width:100%}.drag-handle-icons{display:flex;align-items:center;gap:16px}.drag-indicator-right{color:#fff;font-size:18px;width:18px;height:18px;cursor:grab;transition:all .2s ease}.minimize-button{color:#fff;font-size:18px;width:18px;height:18px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;transform:translateY(-30%)}.minimize-button:hover{color:#fff;background:#ffffff26}::ng-deep .layer-selector-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 60%,transparent);box-shadow:0 4px 20px #00000026;width:480px;max-width:100%;max-height:700px;min-height:120px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 767px){::ng-deep .layer-selector-body{width:100%;max-height:70vh;min-height:140px}}@media (min-width: 768px) and (max-width: 1024px){::ng-deep .layer-selector-body{width:100%;max-width:445px;max-height:76vh;min-height:110px}}::ng-deep .layer-selector-body .search-section{display:flex;align-items:center;gap:6px;padding:8px 12px 6px}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section{padding:6px 8px 4px;gap:4px}}::ng-deep .layer-selector-body .search-section mat-form-field{flex:1}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;background:#000}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-wrapper{padding-bottom:0;margin-bottom:0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-infix{padding-bottom:6px;min-height:auto}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline{background:#fff}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline-thick{color:#1976d2}::ng-deep .layer-selector-body .search-section mat-form-field input{font-size:13px;padding:3px 0}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section mat-form-field input{font-size:12px}}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-label{color:#fff;font-weight:500;font-size:13px}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-label{font-size:12px}}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-subscript-wrapper{height:0;margin-top:0}::ng-deep .layer-selector-body .search-section mat-icon{color:#fff;cursor:pointer;padding:6px;border-radius:4px;transition:all .2s ease;font-size:24px;width:24px;height:24px;display:flex;justify-content:center;align-items:center}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section mat-icon{font-size:20px;width:20px;height:20px;padding:4px}}::ng-deep .layer-selector-body .search-section mat-icon:hover{color:#f9fafb}::ng-deep .layer-selector-body .item-list{flex:1;overflow-y:auto;max-height:660px;width:100%}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list{padding:4px;max-height:calc(60vh - 80px)}}@media (min-width: 768px) and (max-width: 1024px){::ng-deep .layer-selector-body .item-list{max-height:calc(77vh - 78px)}}::ng-deep .layer-selector-body .item-list .group{overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel{box-shadow:none!important;border-radius:0!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header{padding:0 11px;height:40px;background:#000!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header:hover{background:#333!important}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header{padding:0 20px;height:36px}}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header:hover{background:color-mix(in srgb,#000 60%,transparent)!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title{align-items:center;gap:6px;font-weight:600;color:#bdc1c3cc;font-size:17px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title{gap:4px;font-size:11px}}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon{color:#bdc1c3cc;font-size:16px;width:16px;height:16px;transition:transform .2s ease}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon{font-size:14px;width:14px;height:14px}}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.lightbulb{color:#dfca0e}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-on{color:#4caf50}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-off{color:#f44336}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content{background:#4d4f55}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content .mat-expansion-panel-body{padding:4px 0;background:#000}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content .mat-expansion-panel-body{padding:2px 0}}::ng-deep .layer-selector-body .item-list .group .item-list{padding:0;max-height:none}::ng-deep .layer-selector-body .item-list .group .item-list .layer-description{font-size:13px;padding:0 31px;color:#fffc}::ng-deep .layer-selector-body .item-list .group .item-list .item{width:100%;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:6px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab;font-size:14px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item{gap:4px;padding:6px 8px}}::ng-deep .layer-selector-body .item-list .group .item-list .item:last-child{border-bottom:none}::ng-deep .layer-selector-body .item-list .group .item-list .item:hover{background-color:transparent;transition:all .2s ease}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-left{display:flex;align-items:center;gap:3px;flex:1;min-width:0}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-left span{font-size:13px;word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;white-space:normal;flex:1;min-width:0;color:#fff}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item .item-left span{font-size:11px}}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-center{display:flex;align-items:center;gap:2px;flex-shrink:0;justify-content:center;position:relative;left:0}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-center .icon-label{font-size:11px;opacity:.8;margin-right:4px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item .item-center .icon-label{font-size:9px;margin-right:2px}}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-right{display:flex;align-items:center;flex:1;justify-content:flex-end;min-width:0}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-right input[type=range]{width:80px;height:4px;margin:0;flex-shrink:0}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item .item-right input[type=range]{width:60px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon{flex-shrink:0}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.drag-indicator{color:#fff;font-size:16px;width:16px;height:16px;cursor:grab}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.drag-indicator{font-size:14px;width:14px;height:14px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on{color:#4caf50;font-size:18px;width:18px;height:18px;cursor:pointer;padding:3px;border-radius:3px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on{font-size:16px;width:16px;height:16px;padding:2px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on:hover{background:#4caf5033}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off{color:#f44336;font-size:18px;width:18px;height:18px;cursor:pointer;padding:3px;border-radius:3px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off{font-size:16px;width:16px;height:16px;padding:2px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off:hover{background:#f4433633}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.zoom-off{color:#f44336;font-size:16px;width:16px;height:16px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.zoom-off{font-size:14px;width:14px;height:14px}}::ng-deep .mat-expansion-indicator svg{fill:#fff!important}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 15px #00000026;background:#fff;padding:10px 12px}.cdk-drag-placeholder{opacity:.3}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.item-list.cdk-drop-list-dragging .item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.power-on{color:#4caf50}.power-off{color:#f44336}.display-none{display:none}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar{width:12px}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-track{background:#757474;border-radius:8px}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb{background:#1a1c1f;border-radius:8px;border:2px solid #2a2c30}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb:hover{background:#0f1012}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button{width:12px;height:16px;background:#2a2c30;border:1px solid #1a1c1f}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:decrement{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 4l-4 4h8z'/%3E%3C/svg%3E\") no-repeat center;border-radius:8px 8px 0 0}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:decrement:hover{background-color:#1a1c1f}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:increment{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 8l4-4H2z'/%3E%3C/svg%3E\") no-repeat center;border-radius:0 0 8px 8px}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:increment:hover{background-color:#1a1c1f}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
541
603
  }
542
604
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerSelectorComponent, decorators: [{
543
605
  type: Component,
544
606
  args: [{ selector: 'lib-layer-selector', imports: [MatFormFieldModule, CommonModule, MatIconModule, FormsModule, DragDropModule,
545
- MatExpansionModule, MatInputModule], template: "<div #layerSelectorIcon id=\"layerSelector\" class=\"ol-unselectable ol-control layer-selector-icon\">\n <mat-icon (click)=\"toggleLayerSelector()\">layers</mat-icon>\n</div>\n<div #layerSelectorBody [class.display-none]=\"!showSelector\" class=\"layer-selector-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"ol-unselectable ol-control layer-selector-body\">\n <div class=\"search-section\">\n <mat-form-field appearance=\"outline\" class=\"w-full\">\n <mat-label>Filtrer</mat-label>\n <input \n matInput \n type=\"text\" \n [(ngModel)]=\"searchText\" \n (ngModelChange)=\"filteredLayerGroups=setfilteredGroups()\"\n placeholder=\"Skriv for at filtrere...\"\n />\n </mat-form-field>\n <mat-icon (click)=\"clearSearchText()\">undo</mat-icon>\n </div>\n \n <div\n cdkDropList\n [cdkDropListData]=\"filteredLayerGroups\"\n (cdkDropListDropped)=\"dropGroup($event)\"\n class=\"item-list\">\n @for (group of filteredLayerGroups; track group.id; let gIndex = $index) {\n <div class=\"group\" cdkDrag cdkDragPreviewDisabled>\n <mat-expansion-panel [(expanded)]=\"group.expanded\">\n <mat-expansion-panel-header>\n <mat-panel-title>\n @if (group.expanded) {\n <mat-icon>arrow_upward</mat-icon>\n }\n @if (!group.expanded) {\n <mat-icon>arrow_downward</mat-icon> \n }\n {{ group.name }} \n <mat-icon class=\"lightbulb\">lightbulb</mat-icon>\n ({{ group.noOfVisibleLayers }}/{{ group.layers.length }})\n @if (group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-on\">power</mat-icon>(t\u00E6nd)\n }\n @if (!group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-off\">power_off</mat-icon>(sluk)\n }\n </mat-panel-title>\n </mat-expansion-panel-header>\n <!-- This is only shown during drag -->\n <!-- <div *cdkDragPreview class=\"drag-preview\">\n {{ group.name }}\n </div> -->\n\n <!-- Placeholder to avoid jump -->\n <!-- <div *cdkDragPlaceholder class=\"drag-placeholder\"></div> -->\n\n <div\n cdkDropList\n [cdkDropListData]=\"group.layers\"\n (cdkDropListDropped)=\"dropLayer($event, group)\"\n class=\"item-list\">\n @for (layer of group.layers; track layer.id; let iIndex = $index) {\n <mat-expansion-panel expanded=\"true\" [disabled]=\"!showLegend\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" cdkDrag cdkDragPreviewDisabled>\n <mat-icon class=\"drag-indicator\">drag_indicator</mat-icon>\n <span>{{ layer.name }}</span>\n @if (layer.maxZoom < currentZoomLevel || layer.minZoom > currentZoomLevel) {\n <mat-icon class=\"zoom-off\">browser_not_supported</mat-icon>(zoom)\n }\n @if (layer.hasErrors) {\n <mat-icon class=\"zoom-off\">wifi_off</mat-icon>(fejle)\n }\n @if (layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-on\">power</mat-icon>(t\u00E6nd)\n }\n @if (!layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-off\">power_off</mat-icon>(sluk)\n }\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"layer.opacity\"\n (click)=\"stopDrag($event)\"\n (input)=\"updateOpacity(layer)\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @if (showLegend) {\n <img [src]=\"legendUrl\" class=\"legend-thumbnail\"/>\n }\n </mat-expansion-panel>\n }\n </div>\n </mat-expansion-panel>\n </div>\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .layer-selector-icon{position:absolute;left:auto;right:4em;bottom:.5em;z-index:1000}::ng-deep .layer-selector-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .layer-selector-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}.layer-selector-body-wrapper{position:absolute;left:auto;right:4em;bottom:4em;z-index:1000;cursor:grab}.layer-selector-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.layer-selector-body-wrapper .ol-control{border-radius:0}.drag-handle-selector{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 40%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab;box-shadow:0 -2px 8px #0003}.drag-handle-selector mat-icon{color:#fff;font-size:20px;width:20px;height:20px}::ng-deep .layer-selector-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 40%,transparent);box-shadow:0 4px 20px #00000026;width:480px;max-height:500px;overflow:hidden;display:flex;flex-direction:column}::ng-deep .layer-selector-body .search-section{display:flex;align-items:center;gap:6px;padding:8px 12px 6px}::ng-deep .layer-selector-body .search-section mat-form-field{flex:1}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-text-field-wrapper{padding-bottom:0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-wrapper{padding-bottom:0;margin-bottom:0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-infix{padding-bottom:6px;min-height:auto}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline{background:#fff}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline-thick{color:#1976d2}::ng-deep .layer-selector-body .search-section mat-form-field input{font-size:13px;padding:3px 0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-label{color:#fff;font-weight:500;font-size:13px}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-subscript-wrapper{height:0;margin-top:0}::ng-deep .layer-selector-body .search-section mat-icon{color:#fff;cursor:pointer;padding:6px;border-radius:4px;transition:all .2s ease;font-size:24px;width:24px;height:24px;display:flex;justify-content:center;align-items:center}::ng-deep .layer-selector-body .search-section mat-icon:hover{color:#f9fafb}::ng-deep .layer-selector-body .item-list{flex:1;overflow-y:auto;padding:6px;max-height:400px}::ng-deep .layer-selector-body .item-list .group{margin-bottom:6px;overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel{box-shadow:none!important;border-radius:0!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header{padding:0 12px;height:40px;background:color-mix(in srgb,#000 55%,transparent)}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header:hover{background:color-mix(in srgb,#000 60%,transparent)!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title{align-items:center;gap:6px;font-weight:600;color:#fff;font-size:13px}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon{color:#fff;font-size:16px;width:16px;height:16px;transition:transform .2s ease}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.lightbulb{color:#dfca0e}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-on{color:#4caf50}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-off{color:#f44336}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content{background:color-mix(in srgb,#000 40%,transparent)}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content .mat-expansion-panel-body{padding:4px 0}::ng-deep .layer-selector-body .item-list .group .item-list{padding:0;max-height:none}::ng-deep .layer-selector-body .item-list .group .item-list .item{display:flex;align-items:center;gap:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}::ng-deep .layer-selector-body .item-list .group .item-list .item:last-child{border-bottom:none}::ng-deep .layer-selector-body .item-list .group .item-list .item:hover{background-color:#0000004d;transition:all .2s ease}::ng-deep .layer-selector-body .item-list .group .item-list .item.cdk-drag-preview{background:#fff;box-shadow:0 4px 12px #00000026;border-radius:4px}::ng-deep .layer-selector-body .item-list .group .item-list .item.cdk-drag-placeholder{background:#e3f2fd;opacity:.6}::ng-deep .layer-selector-body .item-list .group .item-list .item.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon{flex-shrink:0}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.drag-indicator{color:#fff;font-size:16px;width:16px;height:16px;cursor:grab}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on{color:#4caf50;font-size:18px;width:18px;height:18px;cursor:pointer;margin-left:auto;padding:3px;border-radius:3px}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on:hover{background:#4caf5033}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.zoom-off{color:#f44336;font-size:16px;width:16px;height:16px}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off{color:#f44336;font-size:18px;width:18px;height:18px;cursor:pointer;margin-left:auto;padding:3px;border-radius:3px}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off:hover{background:#f4433633}::ng-deep .layer-selector-body .item-list .group .item-list .item>:nth-child(2){flex:1;font-size:13px;color:#fff;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .layer-selector-body .item-list .group .item-list .item input[type=range]{width:80px;height:4px;margin:0 4px;flex-shrink:0}::ng-deep .mat-expansion-indicator svg{fill:#fff!important}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 15px #00000026;background:#fff;padding:10px 12px}.cdk-drag-placeholder{opacity:.3}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.item-list.cdk-drop-list-dragging .item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.power-on{color:#4caf50}.power-off{color:#f44336}.display-none{display:none}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar{width:8px;border-radius:10px;border:5px solid transparent}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb{background:#0000004d;border:5px solid transparent;border-radius:10px;background-clip:padding-box}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb:hover{background:#0006;background-clip:padding-box;border:3px solid transparent}\n"] }]
607
+ MatExpansionModule, MatInputModule, MatTooltipModule], template: "<div #layerSelectorIcon id=\"layerSelector\" class=\"ol-unselectable ol-control layer-selector-icon\">\n <mat-icon (click)=\"toggleLayerSelector()\">layers</mat-icon>\n</div>\n<div #layerSelectorBody [class.display-none]=\"!showSelector\" class=\"layer-selector-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <div class=\"drag-handle-content\">\n <div class=\"drag-handle-icons\">\n <mat-icon class=\"drag-indicator-right\">open_with</mat-icon>\n <mat-icon class=\"minimize-button\" (click)=\"toggleLayerSelector()\">minimize</mat-icon>\n </div>\n </div>\n </div>\n <div class=\"ol-unselectable ol-control layer-selector-body\">\n <div class=\"search-section\">\n <mat-form-field appearance=\"outline\" class=\"w-full\">\n <mat-label>Filtrer</mat-label>\n <input \n matInput \n type=\"text\" \n [(ngModel)]=\"searchText\" \n (ngModelChange)=\"filteredLayerGroups=setfilteredGroups()\"\n placeholder=\"Skriv for at filtrere...\"\n />\n </mat-form-field>\n <mat-icon (click)=\"clearSearchText()\">undo</mat-icon>\n </div>\n \n <div\n cdkDropList\n [cdkDropListData]=\"filteredLayerGroups\"\n (cdkDropListDropped)=\"dropGroup($event)\"\n class=\"item-list\">\n @for (group of filteredLayerGroups; track group.id; let gIndex = $index) {\n <div class=\"group\" cdkDrag cdkDragPreviewDisabled>\n <mat-expansion-panel [(expanded)]=\"group.expanded\">\n <mat-expansion-panel-header>\n <mat-panel-title>\n @if (group.expanded) {\n <mat-icon>arrow_upward</mat-icon>\n }\n @if (!group.expanded) {\n <mat-icon>arrow_downward</mat-icon> \n }\n {{ group.name }} \n <mat-icon class=\"lightbulb\">lightbulb</mat-icon>\n ({{ group.noOfVisibleLayers }}/{{ group.layers.length }})\n @if (group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-on\" \n matTooltip=\"T\u00E6nd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon> \n }\n @if (!group.visible) {\n <mat-icon (click)=\"toggleGroup($event, group)\" class=\"power-off\"\n matTooltip=\"Sluk\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon>\n }\n </mat-panel-title>\n </mat-expansion-panel-header>\n <!-- This is only shown during drag -->\n <!-- <div *cdkDragPreview class=\"drag-preview\">\n {{ group.name }}\n </div> -->\n\n <!-- Placeholder to avoid jump -->\n <!-- <div *cdkDragPlaceholder class=\"drag-placeholder\"></div> -->\n\n <div\n cdkDropList\n [cdkDropListData]=\"group.layers\"\n (cdkDropListDropped)=\"dropLayer($event, group)\"\n class=\"item-list\">\n @for (layer of group.layers; track layer.id; let iIndex = $index) {\n <mat-expansion-panel expanded=\"false\" [disabled]=\"!layer.description\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" cdkDrag cdkDragPreviewDisabled>\n <div class=\"item-left\">\n <mat-icon class=\"drag-indicator\">drag_indicator</mat-icon>\n <span>{{ layer.name }}</span>\n </div>\n <div class=\"item-center\">\n @if (layer.maxZoom < currentZoomLevel || layer.minZoom > currentZoomLevel) {\n <mat-icon class=\"zoom-off\" \n matTooltip=\"Zoom\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">browser_not_supported\n </mat-icon>\n }\n @if (layer.hasErrors) {\n <mat-icon class=\"zoom-off\" \n matTooltip=\"Fejl\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">priority_high\n </mat-icon>\n\n }\n </div>\n <div class=\"item-right\">\n @if (layer.visible) {\n <mat-icon (click)=\"toggleLayer(layer.id, $event)\" class=\"power-on\" \n matTooltip=\"T\u00E6nd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon>\n }\n @if (!layer.visible) {\n <mat-icon (click)=\"toggleLayer(layer.id, $event)\" class=\"power-off\"\n matTooltip=\"Sluk\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"above\">power_settings_new\n </mat-icon>\n }\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"layer.opacity\"\n (click)=\"stopDrag($event)\"\n (input)=\"updateOpacity(layer)\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n <div class=\"layer-description\">{{ layer.description }}</div>\n @if (showLegend) {\n <img [src]=\"legendUrl\" class=\"legend-thumbnail\"/>\n }\n </mat-expansion-panel>\n }\n </div>\n </mat-expansion-panel>\n </div>\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .layer-selector-icon{position:absolute;left:auto;right:1em;bottom:4.5em;z-index:1000}::ng-deep .layer-selector-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .layer-selector-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}.layer-selector-body-wrapper{position:absolute;left:auto;right:4em;bottom:.2em;z-index:1000;cursor:grab;max-width:calc(100vw - 8em)}.layer-selector-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.layer-selector-body-wrapper .ol-control{border-radius:0}@media (max-width: 767px){.layer-selector-body-wrapper{right:.5em;bottom:4em;max-width:calc(100vw - 7em);left:.5em;width:calc(100vw - 7em)}}@media (min-width: 768px) and (max-width: 1024px){.layer-selector-body-wrapper{right:3.5em;bottom:.5em;max-width:calc(100vw - 2em)}}.drag-handle-selector{display:flex;align-items:center;justify-content:flex-end;border-radius:5px 5px 0 0;padding:5px;cursor:grab;background:color-mix(in srgb,#000 60%,transparent)}.drag-handle-content{display:flex;align-items:center;justify-content:flex-end;width:100%}.drag-handle-icons{display:flex;align-items:center;gap:16px}.drag-indicator-right{color:#fff;font-size:18px;width:18px;height:18px;cursor:grab;transition:all .2s ease}.minimize-button{color:#fff;font-size:18px;width:18px;height:18px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;transform:translateY(-30%)}.minimize-button:hover{color:#fff;background:#ffffff26}::ng-deep .layer-selector-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 60%,transparent);box-shadow:0 4px 20px #00000026;width:480px;max-width:100%;max-height:700px;min-height:120px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 767px){::ng-deep .layer-selector-body{width:100%;max-height:70vh;min-height:140px}}@media (min-width: 768px) and (max-width: 1024px){::ng-deep .layer-selector-body{width:100%;max-width:445px;max-height:76vh;min-height:110px}}::ng-deep .layer-selector-body .search-section{display:flex;align-items:center;gap:6px;padding:8px 12px 6px}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section{padding:6px 8px 4px;gap:4px}}::ng-deep .layer-selector-body .search-section mat-form-field{flex:1}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;background:#000}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-wrapper{padding-bottom:0;margin-bottom:0}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-infix{padding-bottom:6px;min-height:auto}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline{background:#fff}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-outline-thick{color:#1976d2}::ng-deep .layer-selector-body .search-section mat-form-field input{font-size:13px;padding:3px 0}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section mat-form-field input{font-size:12px}}::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-label{color:#fff;font-weight:500;font-size:13px}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section mat-form-field .mat-form-field-label{font-size:12px}}::ng-deep .layer-selector-body .search-section mat-form-field .mat-mdc-form-field-subscript-wrapper{height:0;margin-top:0}::ng-deep .layer-selector-body .search-section mat-icon{color:#fff;cursor:pointer;padding:6px;border-radius:4px;transition:all .2s ease;font-size:24px;width:24px;height:24px;display:flex;justify-content:center;align-items:center}@media (max-width: 767px){::ng-deep .layer-selector-body .search-section mat-icon{font-size:20px;width:20px;height:20px;padding:4px}}::ng-deep .layer-selector-body .search-section mat-icon:hover{color:#f9fafb}::ng-deep .layer-selector-body .item-list{flex:1;overflow-y:auto;max-height:660px;width:100%}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list{padding:4px;max-height:calc(60vh - 80px)}}@media (min-width: 768px) and (max-width: 1024px){::ng-deep .layer-selector-body .item-list{max-height:calc(77vh - 78px)}}::ng-deep .layer-selector-body .item-list .group{overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel{box-shadow:none!important;border-radius:0!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header{padding:0 11px;height:40px;background:#000!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header:hover{background:#333!important}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header{padding:0 20px;height:36px}}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header:hover{background:color-mix(in srgb,#000 60%,transparent)!important}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title{align-items:center;gap:6px;font-weight:600;color:#bdc1c3cc;font-size:17px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title{gap:4px;font-size:11px}}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon{color:#bdc1c3cc;font-size:16px;width:16px;height:16px;transition:transform .2s ease}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon{font-size:14px;width:14px;height:14px}}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.lightbulb{color:#dfca0e}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-on{color:#4caf50}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel mat-expansion-panel-header mat-panel-title mat-icon.power-off{color:#f44336}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content{background:#4d4f55}::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content .mat-expansion-panel-body{padding:4px 0;background:#000}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group mat-expansion-panel .mat-expansion-panel-content .mat-expansion-panel-body{padding:2px 0}}::ng-deep .layer-selector-body .item-list .group .item-list{padding:0;max-height:none}::ng-deep .layer-selector-body .item-list .group .item-list .layer-description{font-size:13px;padding:0 31px;color:#fffc}::ng-deep .layer-selector-body .item-list .group .item-list .item{width:100%;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:6px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab;font-size:14px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item{gap:4px;padding:6px 8px}}::ng-deep .layer-selector-body .item-list .group .item-list .item:last-child{border-bottom:none}::ng-deep .layer-selector-body .item-list .group .item-list .item:hover{background-color:transparent;transition:all .2s ease}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-left{display:flex;align-items:center;gap:3px;flex:1;min-width:0}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-left span{font-size:13px;word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;white-space:normal;flex:1;min-width:0;color:#fff}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item .item-left span{font-size:11px}}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-center{display:flex;align-items:center;gap:2px;flex-shrink:0;justify-content:center;position:relative;left:0}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-center .icon-label{font-size:11px;opacity:.8;margin-right:4px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item .item-center .icon-label{font-size:9px;margin-right:2px}}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-right{display:flex;align-items:center;flex:1;justify-content:flex-end;min-width:0}::ng-deep .layer-selector-body .item-list .group .item-list .item .item-right input[type=range]{width:80px;height:4px;margin:0;flex-shrink:0}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item .item-right input[type=range]{width:60px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon{flex-shrink:0}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.drag-indicator{color:#fff;font-size:16px;width:16px;height:16px;cursor:grab}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.drag-indicator{font-size:14px;width:14px;height:14px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on{color:#4caf50;font-size:18px;width:18px;height:18px;cursor:pointer;padding:3px;border-radius:3px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on{font-size:16px;width:16px;height:16px;padding:2px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-on:hover{background:#4caf5033}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off{color:#f44336;font-size:18px;width:18px;height:18px;cursor:pointer;padding:3px;border-radius:3px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off{font-size:16px;width:16px;height:16px;padding:2px}}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.power-off:hover{background:#f4433633}::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.zoom-off{color:#f44336;font-size:16px;width:16px;height:16px}@media (max-width: 767px){::ng-deep .layer-selector-body .item-list .group .item-list .item mat-icon.zoom-off{font-size:14px;width:14px;height:14px}}::ng-deep .mat-expansion-indicator svg{fill:#fff!important}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 15px #00000026;background:#fff;padding:10px 12px}.cdk-drag-placeholder{opacity:.3}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.item-list.cdk-drop-list-dragging .item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.power-on{color:#4caf50}.power-off{color:#f44336}.display-none{display:none}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar{width:12px}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-track{background:#757474;border-radius:8px}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb{background:#1a1c1f;border-radius:8px;border:2px solid #2a2c30}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-thumb:hover{background:#0f1012}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button{width:12px;height:16px;background:#2a2c30;border:1px solid #1a1c1f}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:decrement{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 4l-4 4h8z'/%3E%3C/svg%3E\") no-repeat center;border-radius:8px 8px 0 0}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:decrement:hover{background-color:#1a1c1f}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:increment{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 8l4-4H2z'/%3E%3C/svg%3E\") no-repeat center;border-radius:0 0 8px 8px}::ng-deep .layer-selector-body .item-list::-webkit-scrollbar-button:vertical:increment:hover{background-color:#1a1c1f}\n"] }]
546
608
  }], propDecorators: { contentIcon: [{
547
609
  type: ViewChild,
548
610
  args: ['layerSelectorIcon', { static: false }]
@@ -623,7 +685,7 @@ class CurrentItemsService {
623
685
  this._mapSubject.next(value);
624
686
  }
625
687
  profile;
626
- _mapSubject = new ReplaySubject();
688
+ _mapSubject = new ReplaySubject(1);
627
689
  map$ = this._mapSubject.asObservable();
628
690
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CurrentItemsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
629
691
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CurrentItemsService, providedIn: 'root' });
@@ -641,7 +703,8 @@ class DrawLayerSourceService {
641
703
  features$ = this._features.asObservable();
642
704
  source = new VectorSource();
643
705
  layer = new VectorLayer({
644
- source: this.source
706
+ source: this.source,
707
+ zIndex: 999
645
708
  });
646
709
  _disabled = false;
647
710
  constructor() {
@@ -704,9 +767,6 @@ class FeatureHelperService {
704
767
  _idCounter = 0;
705
768
  isLocked = (feature) => feature.get(this.FEATURE_LOCKED) === 'true';
706
769
  lock(feature) { feature.set(this.FEATURE_LOCKED, 'true'); }
707
- constructor() {
708
- console.log('FeatureHelperService, constructor');
709
- }
710
770
  setTypeId(feature, typeId) {
711
771
  feature.set(this.FEATURE_TYPE_ID, typeId);
712
772
  }
@@ -722,7 +782,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
722
782
  args: [{
723
783
  providedIn: 'root'
724
784
  }]
725
- }], ctorParameters: () => [] });
785
+ }] });
726
786
 
727
787
  class UndoRedoService {
728
788
  _drawlayerSourceService;
@@ -810,7 +870,7 @@ class GeometrySplitService {
810
870
  const bufferedLine = buffer(lineGeoJSON, bufferMeters, { units: 'meters' });
811
871
  // Move back to 25832
812
872
  bufferedLine.geometry.coordinates = bufferedLine.geometry.coordinates.map(a => a.map(c => proj4('EPSG:4326', 'EPSG:25832', c)));
813
- const overlappingFeatures = vectorSource.getFeatures().filter(f => f.getGeometry()?.intersectsExtent(lineFeature.getGeometry()?.getExtent()));
873
+ const overlappingFeatures = vectorSource.getFeatures().filter(f => !this._featureHelper.isLocked(f) && f.getGeometry()?.intersectsExtent(lineFeature.getGeometry()?.getExtent()));
814
874
  overlappingFeatures.forEach((feature) => {
815
875
  const overlappingFeatureGeoJson = this.geoJsonFormat.writeFeatureObject(feature);
816
876
  const features = featureCollection([overlappingFeatureGeoJson, bufferedLine]);
@@ -865,10 +925,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
865
925
  }]
866
926
  }] });
867
927
 
868
- class highlightService {
869
- constructor() {
870
- console.log('highlightservice, constructor');
871
- }
928
+ class HighlightService {
929
+ _wktFormat = new WKT();
872
930
  _zoomService = inject(ZoomService);
873
931
  _style = new Style({
874
932
  stroke: new Stroke({
@@ -894,7 +952,7 @@ class highlightService {
894
952
  }
895
953
  highlight(feature, zoomToFeatures = true) {
896
954
  if (!Array.isArray(feature)) {
897
- this.highlight([feature]);
955
+ this.highlight([this._ensureFeature(feature)]);
898
956
  return;
899
957
  }
900
958
  // If the feature has a style, it overwrites the style of the layer, so I create a new feature without properties or style.
@@ -903,15 +961,24 @@ class highlightService {
903
961
  this._zoomService.zoomToFeatures(feature);
904
962
  }
905
963
  }
906
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: highlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
907
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: highlightService, providedIn: 'root' });
964
+ _ensureFeature(feature) {
965
+ if (typeof feature === 'string') {
966
+ const newFeature = this._wktFormat.readFeature(feature, { dataProjection: 'EPSG:25832', featureProjection: 'EPSG:25832' });
967
+ return newFeature;
968
+ }
969
+ else {
970
+ return feature;
971
+ }
972
+ }
973
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: HighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
974
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: HighlightService, providedIn: 'root' });
908
975
  }
909
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: highlightService, decorators: [{
976
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: HighlightService, decorators: [{
910
977
  type: Injectable,
911
978
  args: [{
912
979
  providedIn: 'root'
913
980
  }]
914
- }], ctorParameters: () => [] });
981
+ }] });
915
982
 
916
983
  class InteractionHelperService {
917
984
  _current = inject(CurrentItemsService);
@@ -948,6 +1015,9 @@ class MergeFeaturesService {
948
1015
  formatter = new GeoJSON();
949
1016
  _formatterOptions = { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:25832' };
950
1017
  _selectFilter(f, typeId) {
1018
+ if (this._featureHelper.isLocked(f)) {
1019
+ return false;
1020
+ }
951
1021
  if (this._selectedMergeFeature) {
952
1022
  const previusFeatureObject = this.formatter.writeFeatureObject(this._selectedMergeFeature, this._formatterOptions);
953
1023
  const bufferedPreviouslySelected = buffer(previusFeatureObject, 5, { units: 'centimeters' });
@@ -1021,13 +1091,11 @@ class IconsConstants {
1021
1091
 
1022
1092
  class PrintDrawLayerSourceService {
1023
1093
  _current = inject(CurrentItemsService);
1024
- _features = new Subject;
1025
- features$ = this._features.asObservable();
1026
1094
  source = new VectorSource();
1027
1095
  layer = new VectorLayer({
1028
- source: this.source
1096
+ source: this.source,
1097
+ zIndex: 999
1029
1098
  });
1030
- _disabled = false;
1031
1099
  constructor() {
1032
1100
  this.layer.set('PRINTDRAWLAYER', 'true');
1033
1101
  this._initListener();
@@ -1038,49 +1106,213 @@ class PrintDrawLayerSourceService {
1038
1106
  map.addLayer(this.layer);
1039
1107
  }
1040
1108
  });
1041
- this.source.on(['addfeature', 'changefeature', 'removefeature'], evt => {
1042
- if (this._disabled) {
1043
- return;
1109
+ }
1110
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1111
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, providedIn: 'root' });
1112
+ }
1113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, decorators: [{
1114
+ type: Injectable,
1115
+ args: [{
1116
+ providedIn: 'root'
1117
+ }]
1118
+ }], ctorParameters: () => [] });
1119
+
1120
+ class CenterPointService {
1121
+ _settingsHelper = inject(KomponentSettingsHelperService);
1122
+ _current = inject(CurrentItemsService);
1123
+ _drawLayerService = inject(DrawLayerSourceService);
1124
+ _interactionHelper = inject(InteractionHelperService);
1125
+ _geoJson = new GeoJSON();
1126
+ _snackbar = inject(MatSnackBar);
1127
+ _featureHelper = inject(FeatureHelperService);
1128
+ handleFeatureDeleted(featureId) {
1129
+ const centerFeature = this._drawLayerService.source.getFeatures().find(f => f.get('_parentPolyId') == featureId);
1130
+ if (centerFeature) {
1131
+ this._drawLayerService.remove(centerFeature.getId());
1132
+ }
1133
+ }
1134
+ setCenterPoint(style, withinPolygon, callBack) {
1135
+ const style$ = this._settingsHelper.getStyle(style, this._current.profile.styleRepositoryWorkspace, this._current.profile.styleRepositoryGeoserver, 'Point');
1136
+ combineLatest([style$, this._current.map$]).subscribe({
1137
+ next: ([loadedStyle, map]) => {
1138
+ let parentPolyId;
1139
+ const centerDraw = new Draw({
1140
+ type: 'Point',
1141
+ source: this._drawLayerService.source,
1142
+ condition: evt => {
1143
+ if (!withinPolygon) {
1144
+ return true;
1145
+ }
1146
+ // The center needs to be inside a feature, so since turf is great for figuring out if something is in something, move the click and features to EPSG:4326
1147
+ const lonlat = transform(evt.coordinate, 'EPSG:25832', 'EPSG:4326');
1148
+ const pt = point(lonlat);
1149
+ const polygons = this._drawLayerService.source.getFeatures().filter(f => f.getGeometry() && f.getGeometry().getType() === 'Polygon'); // No point in checking linestrings and points
1150
+ const features = this._geoJson.writeFeaturesObject(polygons, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:25832' });
1151
+ const parentPoly = features.features.find(f => booleanPointInPolygon(pt, f));
1152
+ if (!parentPoly) {
1153
+ this._snackbar.open('Centerpunktet skal være inde i en flade', '', { duration: 3000 });
1154
+ return false;
1155
+ }
1156
+ // Save the parent polygon's id on the center. If the parent is deleted, the point will be deleted too
1157
+ parentPolyId = parentPoly.id;
1158
+ return !!parentPoly;
1159
+ },
1160
+ style: loadedStyle
1161
+ });
1162
+ this._interactionHelper.setAsTemp(centerDraw);
1163
+ map.addInteraction(centerDraw);
1164
+ centerDraw.on('drawend', evt => {
1165
+ const existing = this._drawLayerService.source.getFeatures().filter(f => f.get('centerpoint') === true);
1166
+ // There can only be ONE centerpoint, so remove previous if exists
1167
+ if (existing) {
1168
+ this._drawLayerService.source.removeFeatures(existing);
1169
+ }
1170
+ // Mark feature as centerpoint - this is to find it again an remove
1171
+ evt.feature.set('centerpoint', true);
1172
+ evt.feature.set('_parentPolyId', parentPolyId);
1173
+ this._featureHelper.setId(evt.feature);
1174
+ callBack();
1175
+ });
1044
1176
  }
1045
- const features = this.source.getFeatures();
1046
- this._features.next(features);
1047
1177
  });
1048
1178
  }
1049
- get allFeatures() {
1050
- return this.source.getFeatures().map(f => {
1051
- // I want a static copy of the features.
1052
- const newFeature = f.clone();
1053
- // But cloning doesn't include the id and that is used for referencing a few places.
1054
- newFeature.setId(f.getId());
1055
- return newFeature;
1179
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CenterPointService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1180
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CenterPointService, providedIn: 'root' });
1181
+ }
1182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CenterPointService, decorators: [{
1183
+ type: Injectable,
1184
+ args: [{
1185
+ providedIn: 'root'
1186
+ }]
1187
+ }] });
1188
+
1189
+ class ConfirmDialogComponent {
1190
+ dialogRef;
1191
+ data;
1192
+ constructor(dialogRef, data) {
1193
+ this.dialogRef = dialogRef;
1194
+ this.data = data;
1195
+ }
1196
+ choose(choice) {
1197
+ this.dialogRef.close(choice);
1198
+ }
1199
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfirmDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
1200
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ConfirmDialogComponent, isStandalone: true, selector: "app-confirm-dialog", ngImport: i0, template: "\n@if(data.title) {\n <h2 mat-dialog-title>{{ data.title }}</h2>\n}\n<mat-dialog-content>\n <p>{{ data.message }}</p>\n</mat-dialog-content>\n\n<mat-dialog-actions align=\"end\">\n <!-- Sekund\u00E6r handling -->\n <button mat-button (click)=\"choose('secondary')\">\n {{ data.secondaryText }}\n </button>\n\n <!-- Prim\u00E6r handling -->\n <button mat-raised-button color=\"primary\" (click)=\"choose('primary')\">\n {{ data.primaryText }}\n </button>\n</mat-dialog-actions>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }] });
1201
+ }
1202
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfirmDialogComponent, decorators: [{
1203
+ type: Component,
1204
+ args: [{ selector: 'app-confirm-dialog', imports: [CommonModule, MatDialogModule, MatButtonModule, MatDialogTitle, MatDialogContent, MatDialogActions], template: "\n@if(data.title) {\n <h2 mat-dialog-title>{{ data.title }}</h2>\n}\n<mat-dialog-content>\n <p>{{ data.message }}</p>\n</mat-dialog-content>\n\n<mat-dialog-actions align=\"end\">\n <!-- Sekund\u00E6r handling -->\n <button mat-button (click)=\"choose('secondary')\">\n {{ data.secondaryText }}\n </button>\n\n <!-- Prim\u00E6r handling -->\n <button mat-raised-button color=\"primary\" (click)=\"choose('primary')\">\n {{ data.primaryText }}\n </button>\n</mat-dialog-actions>\n" }]
1205
+ }], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
1206
+ type: Inject,
1207
+ args: [MAT_DIALOG_DATA]
1208
+ }] }] });
1209
+
1210
+ class ConfirmDialogService {
1211
+ dialog;
1212
+ constructor(dialog) {
1213
+ this.dialog = dialog;
1214
+ }
1215
+ open(data) {
1216
+ const dialogRef = this.dialog.open(ConfirmDialogComponent, {
1217
+ width: '400px',
1218
+ disableClose: !!data.disableClose,
1219
+ data
1056
1220
  });
1221
+ return dialogRef.afterClosed();
1057
1222
  }
1058
- remove(id) {
1059
- const feature = this.source.getFeatureById(id);
1060
- if (feature) {
1061
- this.source.removeFeature(feature);
1223
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfirmDialogService, deps: [{ token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable });
1224
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfirmDialogService, providedIn: 'root' });
1225
+ }
1226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfirmDialogService, decorators: [{
1227
+ type: Injectable,
1228
+ args: [{ providedIn: 'root' }]
1229
+ }], ctorParameters: () => [{ type: i1$2.MatDialog }] });
1230
+
1231
+ class OverlapService {
1232
+ _drawLayerService = inject(DrawLayerSourceService);
1233
+ _featureHelper = inject(FeatureHelperService);
1234
+ _snackbar = inject(MatSnackBar);
1235
+ _confirmService = inject(ConfirmDialogService);
1236
+ handleOverlap(feature) {
1237
+ const geoJsonFormat = new GeoJSON();
1238
+ const epsilon = 0.1;
1239
+ const overlappingLockedFeatures = this._drawLayerService.source.getFeatures().filter(f => this._featureHelper.isLocked(f) && f.getGeometry()?.intersectsExtent(feature.getGeometry().getExtent()));
1240
+ let newFeatureGeoJson = geoJsonFormat.writeFeatureObject(feature);
1241
+ const orgFeatureArea = area(newFeatureGeoJson);
1242
+ if (overlappingLockedFeatures.length > 0) {
1243
+ const overlappingLockedFeaturesAsGeoJson = overlappingLockedFeatures.map(f => geoJsonFormat.writeFeatureObject(f));
1244
+ const features = featureCollection([newFeatureGeoJson, ...overlappingLockedFeaturesAsGeoJson]);
1245
+ const clipped = difference(features);
1246
+ if (clipped) {
1247
+ const clippedArea = area(clipped.geometry);
1248
+ // The overlap is done by checking extent. To make sure there's an actual change, I check if the areas are diffent
1249
+ // but sometimes, the calculations of the same area can be a bit of. Like 0.01. To make sure that doesn't register as a change
1250
+ // I check that there's actually a change.
1251
+ const actuallyClipped = Math.abs(orgFeatureArea - clippedArea) > epsilon;
1252
+ if (actuallyClipped) {
1253
+ const geom = geoJsonFormat.readGeometry(clipped.geometry);
1254
+ feature.setGeometry(geom);
1255
+ this._snackbar.open("Der var overlap med låste flader, så den indtegnede flade er blevet beskåret", '', { duration: 3000 });
1256
+ }
1257
+ }
1258
+ }
1259
+ // Handle the unlocked.
1260
+ const overlappingUnlockedFeatures = this._drawLayerService.source.getFeatures().filter(f => !this._featureHelper.isLocked(f) && f.getGeometry()?.intersectsExtent(feature.getGeometry().getExtent()));
1261
+ if (overlappingUnlockedFeatures.length === 0) {
1262
+ return of(feature);
1263
+ }
1264
+ else {
1265
+ newFeatureGeoJson = geoJsonFormat.writeFeatureObject(feature);
1266
+ const newFeatureArea = area(newFeatureGeoJson);
1267
+ const unlockedFeaturesAsGeoJson = overlappingUnlockedFeatures.map(f => geoJsonFormat.writeFeatureObject(f));
1268
+ const newClippedFeature = difference(featureCollection([newFeatureGeoJson, ...unlockedFeaturesAsGeoJson]));
1269
+ const areaNewClippedFeature = area(newClippedFeature);
1270
+ if (Math.abs(newFeatureArea - areaNewClippedFeature) < epsilon) {
1271
+ return of(feature);
1272
+ }
1273
+ else {
1274
+ const open$ = this._confirmService.open({
1275
+ primaryText: 'Nye',
1276
+ secondaryText: 'Eksisterende',
1277
+ disableClose: true,
1278
+ message: 'Den nye flade overlapper med eksisterende flade. Ønsker du at beskære de nye eller de eksisterende?',
1279
+ title: 'Beskæring'
1280
+ });
1281
+ return open$.pipe(map(msg => {
1282
+ if (msg === 'primary') {
1283
+ const newGeometry = geoJsonFormat.readGeometry(newClippedFeature.geometry);
1284
+ feature.setGeometry(newGeometry);
1285
+ return feature;
1286
+ }
1287
+ else {
1288
+ unlockedFeaturesAsGeoJson.forEach(f => {
1289
+ const featureArea = area(f.geometry);
1290
+ const fc = featureCollection([f, newFeatureGeoJson]);
1291
+ const featureDiff = difference(fc);
1292
+ const featureDiffArea = area(featureDiff.geometry);
1293
+ if (Math.abs(featureArea - featureDiffArea) > epsilon) {
1294
+ const existingFeature = this._drawLayerService.source.getFeatureById(f.id);
1295
+ if (existingFeature) {
1296
+ const newGeometry = geoJsonFormat.readGeometry(featureDiff?.geometry);
1297
+ existingFeature.setGeometry(newGeometry);
1298
+ }
1299
+ }
1300
+ });
1301
+ return feature;
1302
+ }
1303
+ }));
1304
+ }
1062
1305
  }
1063
1306
  }
1064
- setFeatures(features) {
1065
- this._disabled = true;
1066
- this.source.clear();
1067
- this.source.addFeatures(features.map(f => {
1068
- const newFeature = f.clone();
1069
- newFeature.setId(f.getId());
1070
- return newFeature;
1071
- }));
1072
- this._features.next(features);
1073
- this._disabled = false;
1074
- }
1075
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1076
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, providedIn: 'root' });
1307
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: OverlapService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1308
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: OverlapService, providedIn: 'root' });
1077
1309
  }
1078
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, decorators: [{
1310
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: OverlapService, decorators: [{
1079
1311
  type: Injectable,
1080
1312
  args: [{
1081
1313
  providedIn: 'root'
1082
1314
  }]
1083
- }], ctorParameters: () => [] });
1315
+ }] });
1084
1316
 
1085
1317
  class ToolboxComponent {
1086
1318
  // Inputs
@@ -1100,9 +1332,12 @@ class ToolboxComponent {
1100
1332
  _featureHelper = inject(FeatureHelperService);
1101
1333
  _undoRedo = inject(UndoRedoService);
1102
1334
  _geomSplitService = inject(GeometrySplitService);
1103
- _highlight = inject(highlightService);
1335
+ _highlight = inject(HighlightService);
1104
1336
  _interactionHelper = inject(InteractionHelperService);
1105
1337
  _mergeService = inject(MergeFeaturesService);
1338
+ _centerPointService = inject(CenterPointService);
1339
+ _overlap = inject(OverlapService);
1340
+ _zoomService = inject(ZoomService);
1106
1341
  _POSITION_STORAGE_KEY = 'toolbox_position';
1107
1342
  _current = inject(CurrentItemsService);
1108
1343
  _originalMapWidth = 0;
@@ -1118,7 +1353,7 @@ class ToolboxComponent {
1118
1353
  [800, 600]
1119
1354
  ];
1120
1355
  printDrawLabel = "";
1121
- drawTool = "point";
1356
+ printDrawTool = "Point";
1122
1357
  selectedGeometrySetting = undefined;
1123
1358
  undoIconBase64 = IconsConstants.undoIconBase64;
1124
1359
  redoIconBase64 = IconsConstants.redoIconBase64;
@@ -1182,9 +1417,21 @@ class ToolboxComponent {
1182
1417
  next: featureStyle => {
1183
1418
  feature.setStyle(featureStyle);
1184
1419
  this._featureHelper.setTypeId(feature, this.selectedGeometrySetting?.typeId || '');
1185
- this._highlight.highlight(feature);
1186
- const extent = buffer$1(feature.getGeometry().getExtent(), 10);
1187
- this.map.getView().fit(extent);
1420
+ this._featureHelper.setId(feature);
1421
+ if (featureType === 'Polygon') {
1422
+ this._overlap.handleOverlap(feature).subscribe({
1423
+ next: f => {
1424
+ if (f) {
1425
+ this._zoomService.zoomToFeatures([f]);
1426
+ this._drawLayerService.source.addFeature(f);
1427
+ }
1428
+ }
1429
+ });
1430
+ }
1431
+ else {
1432
+ this._zoomService.zoomToFeatures([feature]);
1433
+ this._drawLayerService.source.addFeature(feature);
1434
+ }
1188
1435
  }
1189
1436
  });
1190
1437
  }
@@ -1196,6 +1443,14 @@ class ToolboxComponent {
1196
1443
  type: 'Polygon',
1197
1444
  source: this._drawLayerService.source
1198
1445
  });
1446
+ setCenterPoint() {
1447
+ this._clearAllInteractions();
1448
+ this.activeMode = 'center-point';
1449
+ this._centerPointService.setCenterPoint(this.settings.centerPoint.style, this.settings.centerPoint.withinPolygon, () => {
1450
+ this.activeMode = null;
1451
+ this._clearAllInteractions();
1452
+ });
1453
+ }
1199
1454
  _actionSource = new VectorSource();
1200
1455
  clipHole() {
1201
1456
  this._clearAllInteractions();
@@ -1206,7 +1461,7 @@ class ToolboxComponent {
1206
1461
  });
1207
1462
  this._interactionHelper.setAsTemp(clipHoleDraw);
1208
1463
  clipHoleDraw.on('drawend', evt => {
1209
- const overlappingFeatures = this._drawLayerService.source.getFeatures().filter(f => f.getGeometry()?.intersectsExtent(evt.feature.getGeometry().getExtent()));
1464
+ const overlappingFeatures = this._drawLayerService.source.getFeatures().filter(f => !this._featureHelper.isLocked(f) && f.getGeometry()?.intersectsExtent(evt.feature.getGeometry().getExtent()));
1210
1465
  const geoJsonFormat = new GeoJSON();
1211
1466
  const holeGeoJson = geoJsonFormat.writeFeatureObject(evt.feature);
1212
1467
  overlappingFeatures.forEach(f => {
@@ -1276,6 +1531,7 @@ class ToolboxComponent {
1276
1531
  this._interactionHelper.setAsTemp(this.deleteSelect);
1277
1532
  this.deleteSelect.on('select', evt => {
1278
1533
  this._drawLayerService.source.removeFeatures(evt.selected);
1534
+ evt.selected.forEach(f => this._centerPointService.handleFeatureDeleted(f.getId()));
1279
1535
  });
1280
1536
  return this._deleteSelect;
1281
1537
  }
@@ -1292,10 +1548,18 @@ class ToolboxComponent {
1292
1548
  this.activeMode = 'edit-remove';
1293
1549
  const modifyRemove = new Modify({
1294
1550
  source: this._drawLayerService.source,
1551
+ condition: evt => {
1552
+ // first, get all features from the draw-layer
1553
+ const feature = this.map.forEachFeatureAtPixel(evt.pixel, f => f, { layerFilter: l => l == this._drawLayerService.layer });
1554
+ if (!feature) {
1555
+ return false;
1556
+ }
1557
+ return !this._featureHelper.isLocked(feature);
1558
+ },
1295
1559
  // Make sure delete is allowed and other interactions are not.
1296
1560
  deleteCondition: always,
1297
1561
  insertVertexCondition: never,
1298
- snapToPointer: this.snap
1562
+ snapToPointer: this.snap,
1299
1563
  });
1300
1564
  this._interactionHelper.setAsTemp(modifyRemove);
1301
1565
  this.map.addInteraction(modifyRemove);
@@ -1306,10 +1570,18 @@ class ToolboxComponent {
1306
1570
  this.activeMode = 'edit';
1307
1571
  const modify = new Modify({
1308
1572
  source: this._drawLayerService.source,
1573
+ condition: evt => {
1574
+ // first, get all features from the draw-layer
1575
+ const feature = this.map.forEachFeatureAtPixel(evt.pixel, f => f, { layerFilter: l => l == this._drawLayerService.layer });
1576
+ if (!feature) {
1577
+ return false;
1578
+ }
1579
+ return !this._featureHelper.isLocked(feature);
1580
+ },
1309
1581
  // No delete
1310
1582
  deleteCondition: () => false,
1311
1583
  // Allow moving existing and add new points
1312
- condition: always,
1584
+ // condition: always,
1313
1585
  insertVertexCondition: always,
1314
1586
  });
1315
1587
  /* Modify fires changes to features a LOT, so to not flood the UndoRedo service, I disable until ending the modify
@@ -1336,14 +1608,28 @@ class ToolboxComponent {
1336
1608
  next: style => {
1337
1609
  const drawInteraction = new Draw({
1338
1610
  type: geomType,
1339
- source: this._drawLayerService.source,
1611
+ source: new VectorSource(),
1340
1612
  style: style
1341
1613
  });
1614
+ this._undoRedo.disable();
1342
1615
  drawInteraction.on('drawend', evt => {
1343
- console.log("🚀 ~ ToolboxComponent ~ _startDraw ~ evt:", evt);
1344
1616
  this._featureHelper.setTypeId(evt.feature, this.selectedGeometrySetting?.typeId || '');
1345
1617
  this._featureHelper.setId(evt.feature);
1346
1618
  evt.feature.setStyle(style);
1619
+ if (geomType === 'Polygon') {
1620
+ this._overlap.handleOverlap(evt.feature).pipe(filter(f => !!f)).subscribe({
1621
+ next: f => {
1622
+ if (f) {
1623
+ this._undoRedo.enable();
1624
+ this._drawLayerService.source.addFeature(f);
1625
+ }
1626
+ }
1627
+ });
1628
+ }
1629
+ else {
1630
+ this._undoRedo.enable();
1631
+ this._drawLayerService.source.addFeature(evt.feature);
1632
+ }
1347
1633
  });
1348
1634
  this._interactionHelper.setAsTemp(drawInteraction);
1349
1635
  // this._setDrawLayer()
@@ -1357,6 +1643,7 @@ class ToolboxComponent {
1357
1643
  _areaSource = new VectorSource();
1358
1644
  _areaLayer = new VectorLayer({
1359
1645
  source: this._areaSource,
1646
+ zIndex: 999,
1360
1647
  style: (feature) => {
1361
1648
  const geom = feature.getGeometry();
1362
1649
  const area = getArea(geom);
@@ -1382,6 +1669,7 @@ class ToolboxComponent {
1382
1669
  _distanceLabelSource = new VectorSource();
1383
1670
  _distanceLabelLayer = new VectorLayer({
1384
1671
  source: this._distanceLabelSource,
1672
+ zIndex: 999,
1385
1673
  style: (feature) => {
1386
1674
  return new Style({
1387
1675
  text: new Text({
@@ -1396,6 +1684,7 @@ class ToolboxComponent {
1396
1684
  _distanceSource = new VectorSource();
1397
1685
  _distanceLayer = new VectorLayer({
1398
1686
  source: this._distanceSource,
1687
+ zIndex: 999,
1399
1688
  style: (feature) => {
1400
1689
  const geom = feature.getGeometry();
1401
1690
  const length = getLength(geom);
@@ -1544,7 +1833,10 @@ class ToolboxComponent {
1544
1833
  });
1545
1834
  this.map.addInteraction(changeTypeSelect);
1546
1835
  }
1547
- toggleCollapsed() {
1836
+ toggleCollapsed(event) {
1837
+ if (event) {
1838
+ event.stopPropagation();
1839
+ }
1548
1840
  this.collapsed = !this.collapsed;
1549
1841
  if (this.collapsed) {
1550
1842
  this.stopMeasureArea();
@@ -1624,16 +1916,7 @@ class ToolboxComponent {
1624
1916
  }
1625
1917
  doPrint() {
1626
1918
  let htmlElement = this.map.getViewport();
1627
- const activeobjects = htmlElement.querySelector('activeobjects');
1628
- activeobjects.style.visibility = 'hidden';
1629
- const zoom = htmlElement.querySelector('.ol-zoom');
1630
- zoom.style.visibility = 'hidden';
1631
- const mapToolbox = htmlElement.querySelector('map-toolbox');
1632
- mapToolbox.style.visibility = 'hidden';
1633
- const mousePosition = htmlElement.querySelector('.ol-mouse-position');
1634
- mousePosition.style.visibility = 'hidden';
1635
- const layerSelector = htmlElement.querySelector('#layerSelector');
1636
- layerSelector.style.visibility = 'hidden';
1919
+ this._setVisibiltyOnDOMElements(htmlElement, false);
1637
1920
  html2canvas(htmlElement, {
1638
1921
  useCORS: true,
1639
1922
  }).then(canvas => {
@@ -1649,26 +1932,169 @@ class ToolboxComponent {
1649
1932
  }
1650
1933
  link.download = download;
1651
1934
  link.click();
1652
- activeobjects.style.visibility = 'visible';
1653
- zoom.style.visibility = 'visible';
1654
- mapToolbox.style.visibility = 'visible';
1655
- mousePosition.style.visibility = 'visible';
1656
- layerSelector.style.visibility = 'visible';
1935
+ this._setVisibiltyOnDOMElements(htmlElement, true);
1657
1936
  });
1658
1937
  }
1938
+ _setVisibiltyOnDOMElements(baseElement, visible) {
1939
+ let visibilityValue = 'hidden';
1940
+ if (visible) {
1941
+ visibilityValue = 'visible';
1942
+ }
1943
+ const activeobjects = baseElement.querySelector('activeobjects');
1944
+ if (activeobjects) {
1945
+ activeobjects.style.visibility = visibilityValue;
1946
+ }
1947
+ const zoom = baseElement.querySelector('.ol-zoom');
1948
+ if (zoom) {
1949
+ zoom.style.visibility = visibilityValue;
1950
+ }
1951
+ const mapToolbox = baseElement.querySelector('map-toolbox');
1952
+ if (mapToolbox) {
1953
+ mapToolbox.style.visibility = visibilityValue;
1954
+ }
1955
+ const mousePosition = baseElement.querySelector('.ol-mouse-position');
1956
+ if (mousePosition) {
1957
+ mousePosition.style.visibility = visibilityValue;
1958
+ }
1959
+ const layerSelector = baseElement.querySelector('.layer-selector-body-wrapper');
1960
+ if (layerSelector) {
1961
+ layerSelector.style.visibility = visibilityValue;
1962
+ }
1963
+ }
1659
1964
  startDrawMode() {
1660
1965
  if (this._active === 'PrintDraw') {
1661
1966
  this._active = 'No';
1967
+ this._removePrintDrawToolInteraction();
1968
+ this.activeMode = null;
1969
+ this.printDrawTool = 'Point';
1662
1970
  return;
1663
1971
  }
1664
1972
  this._active = 'PrintDraw';
1973
+ this._clearAllInteractions();
1974
+ this._addPrintDrawToolInteraction();
1975
+ this.activeMode = null;
1976
+ this.printDrawTool = 'Point';
1977
+ }
1978
+ handlePrintDrawToolChanged() {
1979
+ if (this.active === 'PrintDraw') {
1980
+ this._removePrintDrawToolInteraction();
1981
+ this._addPrintDrawToolInteraction();
1982
+ }
1983
+ }
1984
+ handleClearPrintDrawFeatures() {
1985
+ this._printDrawLayerService.source.clear();
1986
+ }
1987
+ printDraw;
1988
+ _addPrintDrawToolInteraction() {
1989
+ if (this.active === 'PrintDraw') {
1990
+ switch (this.printDrawTool) {
1991
+ case 'Arrow':
1992
+ this.printDraw = new Draw({
1993
+ source: this._printDrawLayerService.source,
1994
+ type: 'LineString',
1995
+ });
1996
+ break;
1997
+ case 'Square':
1998
+ this.printDraw = new Draw({
1999
+ source: this._printDrawLayerService.source,
2000
+ type: 'Circle',
2001
+ geometryFunction: createRegularPolygon(4)
2002
+ });
2003
+ break;
2004
+ case 'Rectangle':
2005
+ this.printDraw = new Draw({
2006
+ source: this._printDrawLayerService.source,
2007
+ type: 'Circle',
2008
+ geometryFunction: createBox()
2009
+ });
2010
+ break;
2011
+ default:
2012
+ this.printDraw = new Draw({
2013
+ source: this._printDrawLayerService.source,
2014
+ type: this.printDrawTool,
2015
+ });
2016
+ break;
2017
+ }
2018
+ this.printDraw.on('drawend', evt => {
2019
+ const feature = evt.feature;
2020
+ feature.set("printDrawLabel", this.printDrawLabel);
2021
+ feature.set("printDrawTool", this.printDrawTool);
2022
+ if (this.printDrawTool === 'Arrow') {
2023
+ feature.setStyle((feature) => {
2024
+ const styles = this._getDrawToolStyle(feature);
2025
+ const geom = feature.getGeometry();
2026
+ const rot = this._lastSegmentRotation(geom);
2027
+ const arrowHead = new RegularShape({
2028
+ points: 3,
2029
+ radius: 10,
2030
+ angle: Math.PI / 2,
2031
+ rotation: -rot,
2032
+ rotateWithView: true,
2033
+ stroke: new Stroke({ color: '#1f6feb', width: 3 })
2034
+ });
2035
+ const endCoord = geom.getCoordinateAt(1);
2036
+ const arrowEndStyle = new Style({
2037
+ image: arrowHead,
2038
+ geometry: () => new Point(endCoord)
2039
+ });
2040
+ styles.push(arrowEndStyle);
2041
+ return styles;
2042
+ });
2043
+ }
2044
+ else {
2045
+ feature.setStyle((feature) => this._getDrawToolStyle(feature));
2046
+ }
2047
+ });
2048
+ }
2049
+ this.map.addInteraction(this.printDraw);
2050
+ this._interactionHelper.setAsTemp(this.printDraw);
2051
+ }
2052
+ _removePrintDrawToolInteraction() {
2053
+ this.map.removeInteraction(this.printDraw);
2054
+ }
2055
+ _lastSegmentRotation(lineString) {
2056
+ const coords = lineString.getCoordinates();
2057
+ if (!coords || coords.length < 2)
2058
+ return 0;
2059
+ const [x1, y1] = coords[coords.length - 2];
2060
+ const [x2, y2] = coords[coords.length - 1];
2061
+ return Math.atan2(y2 - y1, x2 - x1);
2062
+ }
2063
+ _getDrawToolStyle(feature) {
2064
+ const textStyle = new Style({
2065
+ text: new Text({
2066
+ text: feature.get("printDrawLabel"),
2067
+ font: '12px Calibri,sans-serif',
2068
+ fill: new Fill({ color: '#000' }),
2069
+ stroke: new Stroke({ color: '#fff', width: 3 }),
2070
+ placement: 'point'
2071
+ })
2072
+ });
2073
+ const lineStyle = new Style({
2074
+ stroke: new Stroke({
2075
+ color: '#1f6feb',
2076
+ width: 3
2077
+ })
2078
+ });
2079
+ const circleStyle = new Style({
2080
+ image: new CircleStyle({
2081
+ radius: 5,
2082
+ fill: new Fill({ color: '#7da8e9ff' }), // teal fill
2083
+ stroke: new Stroke({ color: '#1f6feb', width: 2 }),
2084
+ })
2085
+ });
2086
+ let styles = [textStyle, lineStyle];
2087
+ if (feature.get("printDrawTool") === 'Point') {
2088
+ styles.push(circleStyle);
2089
+ }
2090
+ return styles;
1665
2091
  }
1666
2092
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ToolboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1667
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ToolboxComponent, isStandalone: true, selector: "map-toolbox", inputs: { map: "map", showMeasureDistance: "showMeasureDistance", showMeasureArea: "showMeasureArea", collapsed: "collapsed", settings: "settings", profile: "profile", WKTInputEnabled: "WKTInputEnabled", deleteEnabled: "deleteEnabled" }, ngImport: i0, template: "<div class=\"toolbox-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\"\n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\">\n <div class=\"drag-handle-toolbox\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"toolbox-container\">\n <mat-icon class=\"toggle-icon\" (click)=\"toggleCollapsed()\">{{ collapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\n @if(!collapsed) {\n <div class=\"toolbox-content\">\n @if (settings.geometryTypeSettings && settings.geometryTypeSettings.length) {\n <mat-select class=\"geometry-selector\" (selectionChange)=\"settingsChanged($event)\" [(ngModel)]=\"selectedGeometrySetting\" [compareWith]=\"compareGeometrySetting\">\n @for (setting of settings.geometryTypeSettings; track setting) {\n <mat-option [value]=\"setting\">{{setting.typeName}}</mat-option>\n }\n </mat-select> \n }\n <div class=\"all-tools-container\">\n <div class=\"main-tools\">\n @if(!settings?.undoDisabled) {\n <img \n [src]=\"undoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"undo()\" \n matTooltip=\"Fortryd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Undo\">\n\n <img \n [src]=\"redoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"redo()\" \n matTooltip=\"Gentag\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Redo\">\n }\n <mat-slide-toggle [(ngModel)]=\"snap\" (change)=\"onSnapChange()\">Snap</mat-slide-toggle>\n @if(settings.editEnabled) {\n <img \n [src]=\"editIconBase64\" \n [class.active]=\"activeMode === 'edit'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEdit()\" \n matTooltip=\"Rediger\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Rediger\">\n\n <img \n [src]=\"removePointsIconBase64\" \n [class.active]=\"activeMode === 'edit-remove'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEditRemovePoints()\" \n matTooltip=\"Fjern punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Fjern punkter\">\n }\n @if(settings.cutHoleEnabled) {\n <img \n [src]=\"trimIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'clip-hole'\" \n (click)=\"clipHole()\" \n matTooltip=\"Klip hul\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Klip hul\">\n }\n @if(settings.splitEnabled) {\n <img \n [src]=\"splitIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'split'\"\n (click)=\"split()\" \n matTooltip=\"Sk\u00E6r over\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Sk\u00E6r over\">\n }\n @if(settings.changeTypeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n [class.active]=\"activeMode === 'change-type'\" \n (click)=\"startChangeType()\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Skift type\" \n matTooltipPosition=\"below\">\n find_replace\n </mat-icon>\n }\n @if(settings.mergeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n (click)=\"startMergeFeatures()\" \n matTooltipPosition=\"below\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Saml flader\" \n [class.active]=\"activeMode === 'merge-features'\">\n merge\n </mat-icon>\n }\n </div>\n @if(selectedGeometrySetting && selectedGeometrySetting.availableGeometryTypes?.length) {\n <div class=\"geometry-tools\">\n @for(geomType of selectedGeometrySetting.availableGeometryTypes;track geomType) {\n @if(geomType === 'Polygon') {\n <img \n [src]=\"polygonIconBase64\" \n [class.active]=\"activeMode === 'draw-polygon'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPolygon()\" \n matTooltip=\"Polygon\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Polygon\">\n }\n @if(geomType === 'LineString') {\n <img \n [src]=\"lineStringIconBase64\" \n [class.active]=\"activeMode === 'draw-linestring'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawLineString()\" \n matTooltip=\"LineString\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"LineString\">\n }\n @if(geomType === 'Point') {\n <img \n [src]=\"pointIconBase64\" \n [class.active]=\"activeMode === 'draw-point'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPoint()\" \n matTooltip=\"Punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Punkter\">\n }\n }\n <img \n [src]=\"wktIconBase64\" \n class=\"compact-icon secondary custom-image-icon\"\n (click)=\"activateShowInputWKT()\" \n matTooltip=\"WKT\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"WKT\">\n </div>\n }\n <div class=\"tool-separator\" *ngIf=\"deleteEnabled || showMeasureDistance || showMeasureArea || profile.showPrint\"></div>\n <div class=\"measurement-print-tools\">\n <div class=\"measurement-tools\">\n @if (deleteEnabled) {\n <img \n [src]=\"deleteIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'delete'\"\n (click)=\"startDelete()\" \n matTooltip=\"Slet\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Slet\">\n }\n @if (showMeasureDistance) {\n <img \n [src]=\"measureDistanceIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-distance'\"\n (click)=\"startMeasureLength()\" \n matTooltip=\"M\u00E5le afstand\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le afstand\">\n }\n @if(showMeasureArea) {\n <img \n [src]=\"measureAreaIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-area'\"\n (click)=\"startMeasureArea()\" \n matTooltip=\"M\u00E5le areal\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le areal\">\n }\n </div>\n @if(profile.showPrint) {\n <div class=\"tool-separator print-separator\"></div>\n <div class=\"print-tools\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Print'\"\n (click)=\"startPrintMode()\" \n matTooltip=\"Udskriv\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Udskriv\">\n <!-- <img \n [src]=\"drawBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Draw'\"\n (click)=\"startDrawMode()\" \n matTooltip=\"Tegn\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Tegn\"> -->\n </div>\n }\n </div>\n </div>\n @if(showInputWKT) {\n <div class=\"wkt-section\">\n <input class=\"compact-input\" [(ngModel)]=\"WKTString\">\n <div class=\"wkt-actions\">\n <button class=\"compact-button primary\" (click)=\"ReadWKT()\">Indl\u00E6s WKT</button>\n <button class=\"compact-button\" (click)=\"cancelWKT()\">Annuller</button>\n </div>\n </div>\n }\n @if(profile.showPrint) {\n @if(active === \"Print\") {\n <div class=\"print-config\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon\"\n (click)=\"doPrint()\" \n alt=\"Udskriv\"> \n <span class=\"icon-separator\">i</span>\n <select id=\"formatSelector\" [(ngModel)]=\"format\">\n <option value=\"image/png\" selected>.PNG</option>\n <option value=\"image/jpeg\">.JPG</option>\n </select>\n <select id=\"dimensionSelector\" [(ngModel)]=\"dimId\" (change)=\"handleDimensionSelected()\">\n <option value=\"99\" selected></option>\n <option value=\"0\">1920 X 1080</option>\n <option value=\"1\">1680 X 1050</option>\n <option value=\"2\">1280 X 800</option>\n <option value=\"3\">800 X 600</option>\n </select>\n <input type=\"text\" [(ngModel)]=\"mapWidth\"/> \n <span class=\"icon-separator\">x</span>\n <input type=\"text\" [(ngModel)]=\"mapHeight\"/>\n <button (click)=\"setNewMapDimensions()\">V\u00E6lg</button>\n </div>\n }\n @if(active === \"PrintDraw\") {\n <div class=\"print-draw-config\">\u00A8\n Label <input type=\"text\" [(ngModel)]=\"printDrawLabel\"/>\n <select id=\"drawToolSelector\" [(ngModel)]=\"drawTool\">\n <option value=\"arrow\" selected>Pil</option>\n <option value=\"point\">Punkt</option>\n </select>\n </div>\n }\n }\n </div>\n }\n </div>\n</div>\n", styles: [".toolbox-wrapper{position:absolute;left:1em;top:31.2em;z-index:1000;cursor:grab}.toolbox-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.drag-handle-toolbox{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 60%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab}.drag-handle-toolbox mat-icon{color:#fff;font-size:18px;width:18px;height:18px}:host{position:relative;display:flex;justify-content:center}:host.expanded{width:auto;min-width:320px;padding:12px}.toolbox-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;padding:10px;width:auto;min-width:32px;transition:all .3s ease;cursor:default}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:22px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:6px}.toggle-icon:hover{color:#1976d2;background:#1976d214}.toolbox-content{display:flex;flex-direction:column;width:100%;gap:10px;animation:slideDown .3s cubic-bezier(.4,0,.2,1)}.all-tools-container{display:flex;flex-direction:row;align-items:center;gap:8px;flex-wrap:nowrap;width:100%;justify-content:flex-start;overflow-x:hidden;padding:8px 0}.all-tools-container::-webkit-scrollbar{height:4px}.all-tools-container::-webkit-scrollbar-thumb{background:#ccc;border-radius:2px}.main-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.main-tools ::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:12px;font-weight:500;color:#fff}.geometry-selector{width:100%}.geometry-selector ::ng-deep .mat-mdc-select{font-size:14px;line-height:1.4;border-radius:6px}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:32px;min-height:32px;padding:0 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);transition:all .2s ease}.geometry-selector ::ng-deep .mat-mdc-select-trigger:hover{background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:14px;font-weight:500;color:#fff}.geometry-selector ::ng-deep .mat-mdc-select-arrow-wrapper{height:16px;transform:scale(.85)}.geometry-selector ::ng-deep .mat-mdc-form-field-infix{min-height:32px;padding:6px 0}.geometry-selector ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mat-mdc-select-panel{min-width:fit-content!important;max-width:320px!important;background:color-mix(in srgb,#000 100%,transparent)!important;border:none!important;border-radius:8px!important;box-shadow:0 8px 24px #0000001f,0 2px 6px #00000014!important;margin-top:6px!important;padding:4px 0!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:14px!important;min-height:36px!important;padding:8px 14px!important;transition:all .15s ease!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option:hover:not(.mat-mdc-option-disabled){background:#444849!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option.mat-active{background:color-mix(in srgb,#000 60%,transparent)!important;color:#fff!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px!important;font-weight:500!important;color:#fff!important}::ng-deep .cdk-overlay-pane{z-index:1001}::ng-deep .cdk-overlay-backdrop{z-index:1000}.geometry-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap;background:color-mix(in srgb,#000 20%,transparent);border-radius:8px;padding:4px 8px;border:1px solid rgba(255,255,255,.1)}.measurement-tools,.print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-tools .compact-icon,.print-tools .compact-icon{transition:all .3s cubic-bezier(.4,0,.2,1)}.measurement-tools .compact-icon.custom-image-icon,.print-tools .compact-icon.custom-image-icon{padding:4px;background:none;border:1px solid rgba(255,255,255,.2)}.measurement-tools .compact-icon.custom-image-icon img,.print-tools .compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:filter .2s ease}.measurement-tools .compact-icon.custom-image-icon.active,.print-tools .compact-icon.custom-image-icon.active{background:linear-gradient(147.38deg,#0ea5e9,#075985);border-color:transparent;box-shadow:0 4px 12px #0ea5e966}.measurement-tools .compact-icon.custom-image-icon.active img,.print-tools .compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1)}.measurement-tools .compact-icon.custom-image-icon.active:hover,.print-tools .compact-icon.custom-image-icon.active:hover{box-shadow:0 6px 20px #0ea5e980}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active),.print-tools .compact-icon.custom-image-icon:hover:not(.active){background:color-mix(in srgb,#000 70%,transparent);border-color:#0ea5e9;box-shadow:0 2px 8px #0ea5e94d}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active) img,.print-tools .compact-icon.custom-image-icon:hover:not(.active) img{filter:brightness(0) invert(.8)}.print-tools .compact-icon{background:linear-gradient(147.38deg,#4f46e5,#3730a3);color:#fff;border:1px solid rgba(255,255,255,.2)}.print-tools .compact-icon.print-icon{background:linear-gradient(147.38deg,#10b981,#047857)}.print-tools .compact-icon.draw-icon{background:linear-gradient(147.38deg,#f59e0b,#d97706)}.print-tools .compact-icon.active{background:linear-gradient(147.38deg,#ef4444,#dc2626);box-shadow:0 4px 12px #ef444466;border-color:transparent;transform:scale(1.05)}.print-tools .compact-icon.active:hover{box-shadow:0 6px 20px #ef444480;transform:scale(1.08)}.print-tools .compact-icon:hover:not(.active){box-shadow:0 4px 12px #0000004d;opacity:.9}.tool-separator{width:1px;height:24px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.3),transparent);margin:0 4px}.tool-separator.print-separator{height:28px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.5),transparent)}.compact-icon{cursor:pointer;color:#fff;transition:all .3s cubic-bezier(.4,0,.2,1);width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;background:color-mix(in srgb,#000 40%,transparent);border:1px solid rgba(255,255,255,.2);box-shadow:0 1px 2px #0000001a;flex-shrink:0}.compact-icon.active{color:#fff;background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent;box-shadow:0 8px 25px #667eea4d;transform:scale(1.05)}.compact-icon.active:hover{box-shadow:0 12px 35px #667eea66;transform:scale(1.08)}.compact-icon:hover:not(.active){color:#fff;background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.compact-icon.custom-image-icon{padding:0;background:none;border:none}.compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:transform .2s ease}.compact-icon.custom-image-icon.active{background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent}.compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1);transform:scale(1.1)}.compact-icon.custom-image-icon:hover:not(.active) img{transform:scale(1.05)}.wkt-section{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid rgba(255,255,255,.1);animation:fadeIn .2s ease}.wkt-actions{display:flex;gap:6px;justify-content:space-between}.compact-button{padding:6px 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);color:#fff;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);text-transform:uppercase;letter-spacing:.4px;min-height:32px;display:flex;align-items:center;justify-content:center;flex:1;box-shadow:0 1px 2px #0000000d}.compact-button.primary.active{background:linear-gradient(135deg,#667eea,#764ba2);box-shadow:0 8px 25px #667eea4d;color:#fff}.compact-button.primary.active:hover{box-shadow:0 12px 35px #667eea66}.compact-button.secondary{background:color-mix(in srgb,#000 20%,transparent);color:#fff}.compact-button.secondary:hover{background:color-mix(in srgb,#5a6268 60%,transparent)}.compact-button:hover:not(.active){background:color-mix(in srgb,#000 70%,transparent);color:#fff}.compact-input{padding:8px 10px;border:none;border-radius:6px;font-size:13px;transition:all .2s ease;background:color-mix(in srgb,#000 60%,transparent);color:#fff}.compact-input:focus{outline:none;border-color:#1976d2;background:color-mix(in srgb,#000 70%,transparent);box-shadow:0 0 0 3px #1976d233}.print-config{display:flex;align-items:center;gap:8px;padding:10px;background:color-mix(in srgb,#000 40%,transparent);border-radius:8px;border:1px solid rgba(255,255,255,.1);margin-top:10px;animation:slideDown .3s ease}.print-config select,.print-config input{background:color-mix(in srgb,#000 60%,transparent);border:1px solid rgba(255,255,255,.2);color:#fff;border-radius:6px;font-size:12px;height:32px;min-height:32px;padding:0 10px}.print-config select:focus,.print-config input:focus{outline:none;border-color:#0ea5e9;box-shadow:0 0 0 2px #0ea5e933}.print-config select{cursor:pointer}.print-config option{background:color-mix(in srgb,#000 98%,transparent)!important;border:none!important}.print-config input{width:60px;text-align:center}.print-config button{background:linear-gradient(147.38deg,#10b981,#047857);color:#fff;border:none;padding:6px 12px;border-radius:4px;font-size:12px;cursor:pointer;transition:all .2s ease}.print-config button:hover{box-shadow:0 4px 12px #10b9814d}.print-config .icon-separator{color:#70706f}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes pulse{0%{box-shadow:0 0 #667eeab3}70%{box-shadow:0 0 0 6px #667eea00}to{box-shadow:0 0 #667eea00}}.compact-icon.active{animation:pulse 2s infinite}@media (max-width: 768px){.toolbox-wrapper{left:.5em;top:8em}:host{padding:8px;min-width:32px}:host.expanded{min-width:280px;padding:10px}.all-tools-container{gap:6px;padding-bottom:4px;-ms-overflow-style:none;scrollbar-width:none}.all-tools-container::-webkit-scrollbar{display:none}.main-tools,.geometry-tools,.measurement-print-tools{gap:4px}.compact-icon{width:28px;height:28px;flex-shrink:0}.measurement-print-tools{padding:3px 6px}::ng-deep .mat-mdc-select-panel{max-width:280px!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:13px!important;min-height:32px!important;padding:6px 12px!important}.print-config{flex-wrap:wrap;justify-content:center}.print-config select,.print-config input{font-size:11px;padding:3px 6px}.print-config input{width:50px}.print-config button{padding:4px 8px;font-size:11px}}@media (max-width: 480px){.toolbox-wrapper{transform-origin:left top}.geometry-tools{gap:4px}.measurement-print-tools{gap:4px;flex-wrap:wrap}.compact-button{font-size:10px;letter-spacing:.2px}.print-config{gap:6px}.print-config select,.print-config input{font-size:10px}.print-config button{flex:1;min-width:60px}}::ng-deep .mat-mdc-simple-snack-bar{background-color:#fff!important}::ng-deep .mat-mdc-tooltip{--mdc-plain-tooltip-container-color: #050505 !important;--mdc-plain-tooltip-supporting-text-color: white !important;border-radius:6px}::ng-deep .mat-mdc-tooltip .mdc-tooltip__surface{background-color:#050505!important;color:#fff!important;border-radius:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: i4$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i8.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
2093
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ToolboxComponent, isStandalone: true, selector: "map-toolbox", inputs: { map: "map", showMeasureDistance: "showMeasureDistance", showMeasureArea: "showMeasureArea", collapsed: "collapsed", settings: "settings", profile: "profile", WKTInputEnabled: "WKTInputEnabled", deleteEnabled: "deleteEnabled" }, ngImport: i0, template: "<div class=\"toolbox-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\"\n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\">\n <div class=\"drag-handle-toolbox\" cdkDragHandle>\n <mat-icon>handyman</mat-icon>\n <mat-icon class=\"toggle-icon\" (click)=\"toggleCollapsed($event)\">{{ collapsed ? 'flip_to_front' : 'remove' }}</mat-icon> </div>\n <div class=\"toolbox-container\" [class.collapsed]=\"collapsed\">\n @if(!collapsed) {\n <div class=\"toolbox-content\">\n @if (settings.geometryTypeSettings && settings.geometryTypeSettings.length) {\n <mat-select class=\"geometry-selector\" (selectionChange)=\"settingsChanged($event)\" [(ngModel)]=\"selectedGeometrySetting\" [compareWith]=\"compareGeometrySetting\">\n @for (setting of settings.geometryTypeSettings; track setting) {\n <mat-option [value]=\"setting\">{{setting.typeName}}</mat-option>\n }\n </mat-select> \n }\n <div class=\"all-tools-container\">\n <div class=\"main-tools\">\n @if(!settings?.undoDisabled) {\n <img \n [src]=\"undoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"undo()\" \n matTooltip=\"Fortryd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Undo\">\n\n <img \n [src]=\"redoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"redo()\" \n matTooltip=\"Gentag\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Redo\">\n }\n <mat-slide-toggle [(ngModel)]=\"snap\" (change)=\"onSnapChange()\">Snap</mat-slide-toggle>\n @if(settings.editEnabled) {\n <img \n [src]=\"editIconBase64\" \n [class.active]=\"activeMode === 'edit'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEdit()\" \n matTooltip=\"Rediger\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Rediger\">\n\n <img \n [src]=\"removePointsIconBase64\" \n [class.active]=\"activeMode === 'edit-remove'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEditRemovePoints()\" \n matTooltip=\"Fjern punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Fjern punkter\">\n }\n @if(settings.cutHoleEnabled) {\n <img \n [src]=\"trimIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'clip-hole'\" \n (click)=\"clipHole()\" \n matTooltip=\"Klip hul\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Klip hul\">\n }\n @if(settings.splitEnabled) {\n <img \n [src]=\"splitIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'split'\"\n (click)=\"split()\" \n matTooltip=\"Sk\u00E6r over\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Sk\u00E6r over\">\n }\n @if(settings.changeTypeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n [class.active]=\"activeMode === 'change-type'\" \n (click)=\"startChangeType()\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Skift type\" \n matTooltipPosition=\"below\">\n find_replace\n </mat-icon>\n }\n @if(settings.mergeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n (click)=\"startMergeFeatures()\" \n matTooltipPosition=\"below\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Saml flader\" \n [class.active]=\"activeMode === 'merge-features'\">\n merge\n </mat-icon>\n }\n @if(settings.centerPoint) {\n <mat-icon\n (click)=\"setCenterPoint()\"\n matTooltipPosition=\"below\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"S\u00E6t centerpunkt\" \n [class.active]=\"activeMode === 'center-point'\"\n >adjust</mat-icon>\n }\n </div>\n @if(selectedGeometrySetting && selectedGeometrySetting.availableGeometryTypes?.length) {\n <div class=\"geometry-tools\">\n @for(geomType of selectedGeometrySetting.availableGeometryTypes;track geomType) {\n @if(geomType === 'Polygon') {\n <img \n [src]=\"polygonIconBase64\" \n [class.active]=\"activeMode === 'draw-polygon'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPolygon()\" \n matTooltip=\"Polygon\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Polygon\">\n }\n @if(geomType === 'LineString') {\n <img \n [src]=\"lineStringIconBase64\" \n [class.active]=\"activeMode === 'draw-linestring'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawLineString()\" \n matTooltip=\"LineString\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"LineString\">\n }\n @if(geomType === 'Point') {\n <img \n [src]=\"pointIconBase64\" \n [class.active]=\"activeMode === 'draw-point'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPoint()\" \n matTooltip=\"Punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Punkter\">\n }\n }\n <img \n [src]=\"wktIconBase64\" \n class=\"compact-icon secondary custom-image-icon\"\n (click)=\"activateShowInputWKT()\" \n matTooltip=\"WKT\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"WKT\">\n </div>\n }\n <div class=\"tool-separator\" *ngIf=\"deleteEnabled || showMeasureDistance || showMeasureArea || profile.showPrint\"></div>\n <div class=\"measurement-print-tools\">\n <div class=\"measurement-tools\">\n @if (deleteEnabled) {\n <img \n [src]=\"deleteIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'delete'\"\n (click)=\"startDelete()\" \n matTooltip=\"Slet\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Slet\">\n }\n @if (showMeasureDistance) {\n <img \n [src]=\"measureDistanceIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-distance'\"\n (click)=\"startMeasureLength()\" \n matTooltip=\"M\u00E5le afstand\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le afstand\">\n }\n @if(showMeasureArea) {\n <img \n [src]=\"measureAreaIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-area'\"\n (click)=\"startMeasureArea()\" \n matTooltip=\"M\u00E5le areal\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le areal\">\n }\n </div>\n @if(profile.showPrint) {\n <div class=\"tool-separator print-separator\"></div>\n <div class=\"print-tools\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Print'\"\n (click)=\"startPrintMode()\" \n matTooltip=\"Udskriv\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Udskriv\">\n <img \n [src]=\"drawBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Draw'\"\n (click)=\"startDrawMode()\" \n matTooltip=\"Tegn\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Tegn\">\n </div>\n }\n </div>\n </div>\n @if(showInputWKT) {\n <div class=\"wkt-section\">\n <input class=\"compact-input\" [(ngModel)]=\"WKTString\">\n <div class=\"wkt-actions\">\n <button class=\"compact-button primary\" (click)=\"ReadWKT()\">Indl\u00E6s WKT</button>\n <button class=\"compact-button\" (click)=\"cancelWKT()\">Annuller</button>\n </div>\n </div>\n }\n @if(profile.showPrint) {\n @if(active === \"Print\") {\n <div class=\"print-config\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon\"\n (click)=\"doPrint()\" \n alt=\"Udskriv\"> \n <span class=\"icon-separator\">i</span>\n <select id=\"formatSelector\" [(ngModel)]=\"format\">\n <option value=\"image/png\" selected>.PNG</option>\n <option value=\"image/jpeg\">.JPG</option>\n </select>\n <select id=\"dimensionSelector\" [(ngModel)]=\"dimId\" (change)=\"handleDimensionSelected()\">\n <option value=\"99\" selected></option>\n <option value=\"0\">1920 X 1080</option>\n <option value=\"1\">1680 X 1050</option>\n <option value=\"2\">1280 X 800</option>\n <option value=\"3\">800 X 600</option>\n </select>\n <input type=\"text\" [(ngModel)]=\"mapWidth\"/> \n <span class=\"icon-separator\">x</span>\n <input type=\"text\" [(ngModel)]=\"mapHeight\"/>\n <button (click)=\"setNewMapDimensions()\">V\u00E6lg</button>\n </div>\n }\n @if(active === \"PrintDraw\") {\n <div class=\"print-draw-config\">\n <span class=\"icon-separator\">Label</span>\n <input type=\"text\" [(ngModel)]=\"printDrawLabel\"/>\n <select id=\"drawToolSelector\" [(ngModel)]=\"printDrawTool\" (change)=\"handlePrintDrawToolChanged()\">\n <option value=\"Arrow\" selected>Pil</option>\n <option value=\"Point\">Punkt</option>\n <option value=\"LineString\">Linje</option>\n <option value=\"Polygon\">Polygon</option>\n <option value=\"Circle\">Cirkel</option>\n <option value=\"Square\">Kvadrat</option>\n <option value=\"Rectangle\">Firkant</option>\n </select>\n <button class=\"compact-button\" (click)=\"handleClearPrintDrawFeatures()\">Ryd</button>\n </div>\n }\n }\n </div>\n }\n </div>\n</div>\n", styles: [".toolbox-wrapper{position:absolute;left:1em;top:31.5em;z-index:1000;cursor:grab;max-width:95vw}.toolbox-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.drag-handle-toolbox{display:flex;align-items:center;justify-content:space-between;background:color-mix(in srgb,#000 60%,transparent);padding:2px 10px;cursor:grab;gap:8px;border-radius:5px 5px 0 0}.drag-handle-toolbox mat-icon{color:#fff;font-size:18px;width:18px;height:18px}.drag-handle-toolbox mat-icon:first-child{flex:1;text-align:left}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:18px!important;width:18px!important;height:18px!important;display:flex;align-items:center;justify-content:center;border-radius:4px;padding:2px;flex-shrink:0}.toggle-icon:hover{color:#fff;background:#ffffff26}.toggle-icon:active{background:#ffffff40}:host{position:relative;display:flex;justify-content:center}:host.expanded{width:auto;min-width:320px;padding:12px}.toolbox-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;padding:10px;width:auto;min-width:32px;transition:all .3s ease;cursor:default;border-radius:0 0 5px 5px}.toolbox-container.collapsed{display:none}.toolbox-content{display:flex;flex-direction:column;width:100%;gap:3px;animation:slideDown .3s cubic-bezier(.4,0,.2,1)}.all-tools-container{display:flex;flex-direction:row;align-items:center;flex-wrap:nowrap;width:100%;justify-content:flex-start;overflow-x:hidden}.all-tools-container::-webkit-scrollbar{height:4px}.all-tools-container::-webkit-scrollbar-thumb{background:#ccc;border-radius:2px}.main-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.main-tools ::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:12px;font-weight:500;color:#fff}.geometry-selector{width:100%}.geometry-selector ::ng-deep .mat-mdc-select{font-size:14px;line-height:1.4;border-radius:6px}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:32px;min-height:32px;padding:0 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);transition:all .2s ease}.geometry-selector ::ng-deep .mat-mdc-select-trigger:hover{background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:14px;font-weight:500;color:#fff}.geometry-selector ::ng-deep .mat-mdc-select-arrow-wrapper{height:16px;transform:scale(.85)}.geometry-selector ::ng-deep .mat-mdc-form-field-infix{min-height:32px;padding:6px 0}.geometry-selector ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mat-mdc-select-panel{min-width:fit-content!important;max-width:320px!important;background:color-mix(in srgb,#000 100%,transparent)!important;border:none!important;border-radius:8px!important;box-shadow:0 8px 24px #0000001f,0 2px 6px #00000014!important;margin-top:6px!important;padding:4px 0!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:14px!important;min-height:36px!important;padding:8px 14px!important;transition:all .15s ease!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option:hover:not(.mat-mdc-option-disabled){background:#444849!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option.mat-active{background:color-mix(in srgb,#000 60%,transparent)!important;color:#fff!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px!important;font-weight:500!important;color:#fff!important}::ng-deep .cdk-overlay-pane{z-index:1001}::ng-deep .cdk-overlay-backdrop{z-index:1000}.geometry-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap;background:color-mix(in srgb,#000 20%,transparent);border-radius:8px;padding:4px 8px;border:1px solid rgba(255,255,255,.1)}.measurement-tools,.print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-tools .compact-icon,.print-tools .compact-icon{transition:all .3s cubic-bezier(.4,0,.2,1)}.measurement-tools .compact-icon.custom-image-icon,.print-tools .compact-icon.custom-image-icon{padding:4px;background:none;border:1px solid rgba(255,255,255,.2)}.measurement-tools .compact-icon.custom-image-icon img,.print-tools .compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:filter .2s ease}.measurement-tools .compact-icon.custom-image-icon.active,.print-tools .compact-icon.custom-image-icon.active{background:linear-gradient(147.38deg,#0ea5e9,#075985);border-color:transparent;box-shadow:0 4px 12px #0ea5e966}.measurement-tools .compact-icon.custom-image-icon.active img,.print-tools .compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1)}.measurement-tools .compact-icon.custom-image-icon.active:hover,.print-tools .compact-icon.custom-image-icon.active:hover{box-shadow:0 6px 20px #0ea5e980}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active),.print-tools .compact-icon.custom-image-icon:hover:not(.active){background:color-mix(in srgb,#000 70%,transparent);border-color:#0ea5e9;box-shadow:0 2px 8px #0ea5e94d}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active) img,.print-tools .compact-icon.custom-image-icon:hover:not(.active) img{filter:brightness(0) invert(.8)}.print-tools .compact-icon{background:linear-gradient(147.38deg,#4f46e5,#3730a3);color:#fff;border:1px solid rgba(255,255,255,.2)}.print-tools .compact-icon.print-icon{background:linear-gradient(147.38deg,#10b981,#047857)}.print-tools .compact-icon.draw-icon{background:linear-gradient(147.38deg,#f59e0b,#d97706)}.print-tools .compact-icon.active{background:linear-gradient(147.38deg,#ef4444,#dc2626);box-shadow:0 4px 12px #ef444466;border-color:transparent;transform:scale(1.05)}.print-tools .compact-icon.active:hover{box-shadow:0 6px 20px #ef444480;transform:scale(1.08)}.print-tools .compact-icon:hover:not(.active){box-shadow:0 4px 12px #0000004d;opacity:.9}.tool-separator{width:1px;height:24px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.3),transparent);margin:0 4px}.tool-separator.print-separator{height:28px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.5),transparent)}.compact-icon{cursor:pointer;color:#fff;transition:all .3s cubic-bezier(.4,0,.2,1);width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;background:color-mix(in srgb,#000 40%,transparent);border:1px solid rgba(255,255,255,.2);box-shadow:0 1px 2px #0000001a;flex-shrink:0}.compact-icon.active{color:#fff;background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent;box-shadow:0 8px 25px #667eea4d;transform:scale(1.05)}.compact-icon.active:hover{box-shadow:0 12px 35px #667eea66;transform:scale(1.08)}.compact-icon:hover:not(.active){color:#fff;background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.compact-icon.custom-image-icon{padding:0;background:none;border:none}.compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:transform .2s ease}.compact-icon.custom-image-icon.active{background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent}.compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1);transform:scale(1.1)}.compact-icon.custom-image-icon:hover:not(.active) img{transform:scale(1.05)}.wkt-section{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid rgba(255,255,255,.1);animation:fadeIn .2s ease}.wkt-actions{display:flex;gap:6px;justify-content:space-between}.compact-button{padding:6px 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);color:#fff;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);text-transform:uppercase;letter-spacing:.4px;min-height:32px;display:flex;align-items:center;justify-content:center;flex:1;box-shadow:0 1px 2px #0000000d}.compact-button.primary.active{background:linear-gradient(135deg,#667eea,#764ba2);box-shadow:0 8px 25px #667eea4d;color:#fff}.compact-button.primary.active:hover{box-shadow:0 12px 35px #667eea66}.compact-button.secondary{background:color-mix(in srgb,#000 20%,transparent);color:#fff}.compact-button.secondary:hover{background:color-mix(in srgb,#5a6268 60%,transparent)}.compact-input{padding:8px 10px;border:none;border-radius:6px;font-size:13px;transition:all .2s ease;background:color-mix(in srgb,#000 60%,transparent);color:#fff}.compact-input:focus{outline:none;border-color:#1976d2;background:color-mix(in srgb,#000 70%,transparent);box-shadow:0 0 0 3px #1976d233}.print-config,.print-draw-config{display:flex;align-items:center;gap:8px;padding:5px;background:color-mix(in srgb,#000 40%,transparent);border-radius:8px;border:1px solid rgba(255,255,255,.1);animation:slideDown .3s ease}.print-config select,.print-config input,.print-draw-config select,.print-draw-config input{background:color-mix(in srgb,#000 60%,transparent);border:1px solid rgba(255,255,255,.2);color:#fff;border-radius:6px;font-size:12px;height:32px;min-height:32px;padding:0 10px}.print-config select:focus,.print-config input:focus,.print-draw-config select:focus,.print-draw-config input:focus{outline:none;border-color:#0ea5e9;box-shadow:0 0 0 2px #0ea5e933}.print-config select,.print-draw-config select{cursor:pointer}.print-config option,.print-draw-config option{background:color-mix(in srgb,#000 98%,transparent)!important;border:none!important}.print-config input,.print-draw-config input{width:60px;text-align:center}.print-config button,.print-draw-config button{background:linear-gradient(147.38deg,#10b981,#047857);color:#fff;border:none;padding:6px 12px;border-radius:4px;font-size:12px;cursor:pointer;transition:all .2s ease}.print-config button:hover,.print-draw-config button:hover{box-shadow:0 4px 12px #10b9814d}.print-config .icon-separator,.print-draw-config .icon-separator{color:#fff}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes pulse{0%{box-shadow:0 0 #667eeab3}70%{box-shadow:0 0 0 6px #667eea00}to{box-shadow:0 0 #667eea00}}.compact-icon.active{animation:pulse 2s infinite}@media (max-width: 768px){.toolbox-wrapper{left:.5em;top:8em;max-width:calc(100vw - 2.5em)}.drag-handle-toolbox{padding:3px 6px;gap:6px}.drag-handle-toolbox mat-icon{font-size:16px;width:16px;height:16px}.toggle-icon{font-size:16px!important;width:16px!important;height:16px!important}.toolbox-container{padding:8px;min-width:28px;max-width:calc(100vw - 3em)}:host{padding:8px;min-width:32px}:host.expanded{min-width:280px;padding:10px}.all-tools-container{flex-wrap:wrap;gap:6px;max-height:50vh;overflow-y:auto;padding:0;-ms-overflow-style:none;scrollbar-width:none}.all-tools-container::-webkit-scrollbar{display:none}.main-tools,.geometry-tools,.measurement-print-tools,.print-tools{display:flex;flex-wrap:wrap;justify-content:center;gap:4px}.compact-icon{width:28px;height:28px;flex-shrink:0}.measurement-print-tools{padding:3px 6px}.geometry-selector{width:100%;margin-bottom:8px}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:28px;min-height:28px;padding:0 8px;font-size:12px}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:12px}::ng-deep .mat-mdc-select-panel{max-width:calc(100vw - 2em)!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:13px!important;min-height:32px!important;padding:6px 12px!important}.print-config,.print-draw-config{flex-direction:column;align-items:stretch;gap:6px}.print-config select,.print-config input,.print-draw-config select,.print-draw-config input{font-size:11px;padding:4px 8px;height:28px;min-height:28px}.print-config input,.print-draw-config input{width:50px}.print-config button,.print-draw-config button{padding:4px 8px;font-size:11px;height:28px}.wkt-section .compact-input{font-size:12px;padding:6px 8px}.wkt-section .compact-button{font-size:11px;padding:5px 8px;min-height:28px}::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:11px!important}}@media (max-width: 480px){.toolbox-wrapper{left:.25em;top:6em;transform-origin:left top;max-width:calc(100vw - .5em)}.drag-handle-toolbox{padding:2px 4px;gap:4px}.drag-handle-toolbox mat-icon{font-size:14px;width:14px;height:14px}.toggle-icon{font-size:14px!important;width:14px!important;height:14px!important}.toolbox-container{padding:6px;min-width:24px}.toolbox-content{gap:8px}.all-tools-container{flex-direction:row;align-items:center;max-height:60vh}.main-tools,.geometry-tools{gap:3px;flex-wrap:wrap;justify-content:center}.measurement-print-tools{gap:3px;flex-wrap:wrap;padding:2px 4px;width:100%;justify-content:center}.measurement-tools,.print-tools{gap:3px}.compact-icon{width:26px;height:26px}.tool-separator{display:none}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:26px;min-height:26px;padding:0 6px;font-size:11px}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:11px}.compact-button{font-size:10px;letter-spacing:.2px;padding:4px 6px;min-height:26px}.compact-input{font-size:11px;padding:4px 6px}.print-config,.print-draw-config{gap:4px;padding:6px}.print-config select,.print-config input,.print-draw-config select,.print-draw-config input{font-size:10px;height:26px;min-height:26px;padding:2px 6px}.print-config input,.print-draw-config input{width:45px}.print-config button,.print-draw-config button{flex:1;min-width:60px;font-size:10px;padding:3px 6px;height:26px}.print-config .icon-separator,.print-draw-config .icon-separator{font-size:10px}.wkt-section{gap:6px;padding-top:8px}::ng-deep .mat-mdc-slide-toggle{transform:scale(.9)}::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:10px!important}::ng-deep .mat-mdc-select-panel{max-width:calc(100vw - 1em)!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:12px!important;min-height:28px!important;padding:4px 10px!important}}::ng-deep .mat-mdc-simple-snack-bar{background-color:#fff!important}::ng-deep .mat-mdc-tooltip{--mdc-plain-tooltip-container-color: #050505 !important;--mdc-plain-tooltip-supporting-text-color: white !important;border-radius:6px}::ng-deep .mat-mdc-tooltip .mdc-tooltip__surface{background-color:#050505!important;color:#fff!important;border-radius:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: i4$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i8.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
1668
2094
  }
1669
2095
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ToolboxComponent, decorators: [{
1670
2096
  type: Component,
1671
- args: [{ selector: 'map-toolbox', imports: [FormsModule, CommonModule, MatIconModule, MatOptionModule, MatSelectModule, DragDropModule, MatTooltipModule, MatSlideToggleModule], template: "<div class=\"toolbox-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\"\n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\">\n <div class=\"drag-handle-toolbox\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"toolbox-container\">\n <mat-icon class=\"toggle-icon\" (click)=\"toggleCollapsed()\">{{ collapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\n @if(!collapsed) {\n <div class=\"toolbox-content\">\n @if (settings.geometryTypeSettings && settings.geometryTypeSettings.length) {\n <mat-select class=\"geometry-selector\" (selectionChange)=\"settingsChanged($event)\" [(ngModel)]=\"selectedGeometrySetting\" [compareWith]=\"compareGeometrySetting\">\n @for (setting of settings.geometryTypeSettings; track setting) {\n <mat-option [value]=\"setting\">{{setting.typeName}}</mat-option>\n }\n </mat-select> \n }\n <div class=\"all-tools-container\">\n <div class=\"main-tools\">\n @if(!settings?.undoDisabled) {\n <img \n [src]=\"undoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"undo()\" \n matTooltip=\"Fortryd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Undo\">\n\n <img \n [src]=\"redoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"redo()\" \n matTooltip=\"Gentag\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Redo\">\n }\n <mat-slide-toggle [(ngModel)]=\"snap\" (change)=\"onSnapChange()\">Snap</mat-slide-toggle>\n @if(settings.editEnabled) {\n <img \n [src]=\"editIconBase64\" \n [class.active]=\"activeMode === 'edit'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEdit()\" \n matTooltip=\"Rediger\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Rediger\">\n\n <img \n [src]=\"removePointsIconBase64\" \n [class.active]=\"activeMode === 'edit-remove'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEditRemovePoints()\" \n matTooltip=\"Fjern punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Fjern punkter\">\n }\n @if(settings.cutHoleEnabled) {\n <img \n [src]=\"trimIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'clip-hole'\" \n (click)=\"clipHole()\" \n matTooltip=\"Klip hul\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Klip hul\">\n }\n @if(settings.splitEnabled) {\n <img \n [src]=\"splitIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'split'\"\n (click)=\"split()\" \n matTooltip=\"Sk\u00E6r over\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Sk\u00E6r over\">\n }\n @if(settings.changeTypeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n [class.active]=\"activeMode === 'change-type'\" \n (click)=\"startChangeType()\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Skift type\" \n matTooltipPosition=\"below\">\n find_replace\n </mat-icon>\n }\n @if(settings.mergeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n (click)=\"startMergeFeatures()\" \n matTooltipPosition=\"below\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Saml flader\" \n [class.active]=\"activeMode === 'merge-features'\">\n merge\n </mat-icon>\n }\n </div>\n @if(selectedGeometrySetting && selectedGeometrySetting.availableGeometryTypes?.length) {\n <div class=\"geometry-tools\">\n @for(geomType of selectedGeometrySetting.availableGeometryTypes;track geomType) {\n @if(geomType === 'Polygon') {\n <img \n [src]=\"polygonIconBase64\" \n [class.active]=\"activeMode === 'draw-polygon'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPolygon()\" \n matTooltip=\"Polygon\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Polygon\">\n }\n @if(geomType === 'LineString') {\n <img \n [src]=\"lineStringIconBase64\" \n [class.active]=\"activeMode === 'draw-linestring'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawLineString()\" \n matTooltip=\"LineString\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"LineString\">\n }\n @if(geomType === 'Point') {\n <img \n [src]=\"pointIconBase64\" \n [class.active]=\"activeMode === 'draw-point'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPoint()\" \n matTooltip=\"Punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Punkter\">\n }\n }\n <img \n [src]=\"wktIconBase64\" \n class=\"compact-icon secondary custom-image-icon\"\n (click)=\"activateShowInputWKT()\" \n matTooltip=\"WKT\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"WKT\">\n </div>\n }\n <div class=\"tool-separator\" *ngIf=\"deleteEnabled || showMeasureDistance || showMeasureArea || profile.showPrint\"></div>\n <div class=\"measurement-print-tools\">\n <div class=\"measurement-tools\">\n @if (deleteEnabled) {\n <img \n [src]=\"deleteIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'delete'\"\n (click)=\"startDelete()\" \n matTooltip=\"Slet\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Slet\">\n }\n @if (showMeasureDistance) {\n <img \n [src]=\"measureDistanceIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-distance'\"\n (click)=\"startMeasureLength()\" \n matTooltip=\"M\u00E5le afstand\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le afstand\">\n }\n @if(showMeasureArea) {\n <img \n [src]=\"measureAreaIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-area'\"\n (click)=\"startMeasureArea()\" \n matTooltip=\"M\u00E5le areal\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le areal\">\n }\n </div>\n @if(profile.showPrint) {\n <div class=\"tool-separator print-separator\"></div>\n <div class=\"print-tools\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Print'\"\n (click)=\"startPrintMode()\" \n matTooltip=\"Udskriv\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Udskriv\">\n <!-- <img \n [src]=\"drawBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Draw'\"\n (click)=\"startDrawMode()\" \n matTooltip=\"Tegn\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Tegn\"> -->\n </div>\n }\n </div>\n </div>\n @if(showInputWKT) {\n <div class=\"wkt-section\">\n <input class=\"compact-input\" [(ngModel)]=\"WKTString\">\n <div class=\"wkt-actions\">\n <button class=\"compact-button primary\" (click)=\"ReadWKT()\">Indl\u00E6s WKT</button>\n <button class=\"compact-button\" (click)=\"cancelWKT()\">Annuller</button>\n </div>\n </div>\n }\n @if(profile.showPrint) {\n @if(active === \"Print\") {\n <div class=\"print-config\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon\"\n (click)=\"doPrint()\" \n alt=\"Udskriv\"> \n <span class=\"icon-separator\">i</span>\n <select id=\"formatSelector\" [(ngModel)]=\"format\">\n <option value=\"image/png\" selected>.PNG</option>\n <option value=\"image/jpeg\">.JPG</option>\n </select>\n <select id=\"dimensionSelector\" [(ngModel)]=\"dimId\" (change)=\"handleDimensionSelected()\">\n <option value=\"99\" selected></option>\n <option value=\"0\">1920 X 1080</option>\n <option value=\"1\">1680 X 1050</option>\n <option value=\"2\">1280 X 800</option>\n <option value=\"3\">800 X 600</option>\n </select>\n <input type=\"text\" [(ngModel)]=\"mapWidth\"/> \n <span class=\"icon-separator\">x</span>\n <input type=\"text\" [(ngModel)]=\"mapHeight\"/>\n <button (click)=\"setNewMapDimensions()\">V\u00E6lg</button>\n </div>\n }\n @if(active === \"PrintDraw\") {\n <div class=\"print-draw-config\">\u00A8\n Label <input type=\"text\" [(ngModel)]=\"printDrawLabel\"/>\n <select id=\"drawToolSelector\" [(ngModel)]=\"drawTool\">\n <option value=\"arrow\" selected>Pil</option>\n <option value=\"point\">Punkt</option>\n </select>\n </div>\n }\n }\n </div>\n }\n </div>\n</div>\n", styles: [".toolbox-wrapper{position:absolute;left:1em;top:31.2em;z-index:1000;cursor:grab}.toolbox-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.drag-handle-toolbox{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 60%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab}.drag-handle-toolbox mat-icon{color:#fff;font-size:18px;width:18px;height:18px}:host{position:relative;display:flex;justify-content:center}:host.expanded{width:auto;min-width:320px;padding:12px}.toolbox-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;padding:10px;width:auto;min-width:32px;transition:all .3s ease;cursor:default}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:22px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:6px}.toggle-icon:hover{color:#1976d2;background:#1976d214}.toolbox-content{display:flex;flex-direction:column;width:100%;gap:10px;animation:slideDown .3s cubic-bezier(.4,0,.2,1)}.all-tools-container{display:flex;flex-direction:row;align-items:center;gap:8px;flex-wrap:nowrap;width:100%;justify-content:flex-start;overflow-x:hidden;padding:8px 0}.all-tools-container::-webkit-scrollbar{height:4px}.all-tools-container::-webkit-scrollbar-thumb{background:#ccc;border-radius:2px}.main-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.main-tools ::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:12px;font-weight:500;color:#fff}.geometry-selector{width:100%}.geometry-selector ::ng-deep .mat-mdc-select{font-size:14px;line-height:1.4;border-radius:6px}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:32px;min-height:32px;padding:0 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);transition:all .2s ease}.geometry-selector ::ng-deep .mat-mdc-select-trigger:hover{background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:14px;font-weight:500;color:#fff}.geometry-selector ::ng-deep .mat-mdc-select-arrow-wrapper{height:16px;transform:scale(.85)}.geometry-selector ::ng-deep .mat-mdc-form-field-infix{min-height:32px;padding:6px 0}.geometry-selector ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mat-mdc-select-panel{min-width:fit-content!important;max-width:320px!important;background:color-mix(in srgb,#000 100%,transparent)!important;border:none!important;border-radius:8px!important;box-shadow:0 8px 24px #0000001f,0 2px 6px #00000014!important;margin-top:6px!important;padding:4px 0!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:14px!important;min-height:36px!important;padding:8px 14px!important;transition:all .15s ease!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option:hover:not(.mat-mdc-option-disabled){background:#444849!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option.mat-active{background:color-mix(in srgb,#000 60%,transparent)!important;color:#fff!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px!important;font-weight:500!important;color:#fff!important}::ng-deep .cdk-overlay-pane{z-index:1001}::ng-deep .cdk-overlay-backdrop{z-index:1000}.geometry-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap;background:color-mix(in srgb,#000 20%,transparent);border-radius:8px;padding:4px 8px;border:1px solid rgba(255,255,255,.1)}.measurement-tools,.print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-tools .compact-icon,.print-tools .compact-icon{transition:all .3s cubic-bezier(.4,0,.2,1)}.measurement-tools .compact-icon.custom-image-icon,.print-tools .compact-icon.custom-image-icon{padding:4px;background:none;border:1px solid rgba(255,255,255,.2)}.measurement-tools .compact-icon.custom-image-icon img,.print-tools .compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:filter .2s ease}.measurement-tools .compact-icon.custom-image-icon.active,.print-tools .compact-icon.custom-image-icon.active{background:linear-gradient(147.38deg,#0ea5e9,#075985);border-color:transparent;box-shadow:0 4px 12px #0ea5e966}.measurement-tools .compact-icon.custom-image-icon.active img,.print-tools .compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1)}.measurement-tools .compact-icon.custom-image-icon.active:hover,.print-tools .compact-icon.custom-image-icon.active:hover{box-shadow:0 6px 20px #0ea5e980}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active),.print-tools .compact-icon.custom-image-icon:hover:not(.active){background:color-mix(in srgb,#000 70%,transparent);border-color:#0ea5e9;box-shadow:0 2px 8px #0ea5e94d}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active) img,.print-tools .compact-icon.custom-image-icon:hover:not(.active) img{filter:brightness(0) invert(.8)}.print-tools .compact-icon{background:linear-gradient(147.38deg,#4f46e5,#3730a3);color:#fff;border:1px solid rgba(255,255,255,.2)}.print-tools .compact-icon.print-icon{background:linear-gradient(147.38deg,#10b981,#047857)}.print-tools .compact-icon.draw-icon{background:linear-gradient(147.38deg,#f59e0b,#d97706)}.print-tools .compact-icon.active{background:linear-gradient(147.38deg,#ef4444,#dc2626);box-shadow:0 4px 12px #ef444466;border-color:transparent;transform:scale(1.05)}.print-tools .compact-icon.active:hover{box-shadow:0 6px 20px #ef444480;transform:scale(1.08)}.print-tools .compact-icon:hover:not(.active){box-shadow:0 4px 12px #0000004d;opacity:.9}.tool-separator{width:1px;height:24px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.3),transparent);margin:0 4px}.tool-separator.print-separator{height:28px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.5),transparent)}.compact-icon{cursor:pointer;color:#fff;transition:all .3s cubic-bezier(.4,0,.2,1);width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;background:color-mix(in srgb,#000 40%,transparent);border:1px solid rgba(255,255,255,.2);box-shadow:0 1px 2px #0000001a;flex-shrink:0}.compact-icon.active{color:#fff;background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent;box-shadow:0 8px 25px #667eea4d;transform:scale(1.05)}.compact-icon.active:hover{box-shadow:0 12px 35px #667eea66;transform:scale(1.08)}.compact-icon:hover:not(.active){color:#fff;background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.compact-icon.custom-image-icon{padding:0;background:none;border:none}.compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:transform .2s ease}.compact-icon.custom-image-icon.active{background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent}.compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1);transform:scale(1.1)}.compact-icon.custom-image-icon:hover:not(.active) img{transform:scale(1.05)}.wkt-section{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid rgba(255,255,255,.1);animation:fadeIn .2s ease}.wkt-actions{display:flex;gap:6px;justify-content:space-between}.compact-button{padding:6px 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);color:#fff;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);text-transform:uppercase;letter-spacing:.4px;min-height:32px;display:flex;align-items:center;justify-content:center;flex:1;box-shadow:0 1px 2px #0000000d}.compact-button.primary.active{background:linear-gradient(135deg,#667eea,#764ba2);box-shadow:0 8px 25px #667eea4d;color:#fff}.compact-button.primary.active:hover{box-shadow:0 12px 35px #667eea66}.compact-button.secondary{background:color-mix(in srgb,#000 20%,transparent);color:#fff}.compact-button.secondary:hover{background:color-mix(in srgb,#5a6268 60%,transparent)}.compact-button:hover:not(.active){background:color-mix(in srgb,#000 70%,transparent);color:#fff}.compact-input{padding:8px 10px;border:none;border-radius:6px;font-size:13px;transition:all .2s ease;background:color-mix(in srgb,#000 60%,transparent);color:#fff}.compact-input:focus{outline:none;border-color:#1976d2;background:color-mix(in srgb,#000 70%,transparent);box-shadow:0 0 0 3px #1976d233}.print-config{display:flex;align-items:center;gap:8px;padding:10px;background:color-mix(in srgb,#000 40%,transparent);border-radius:8px;border:1px solid rgba(255,255,255,.1);margin-top:10px;animation:slideDown .3s ease}.print-config select,.print-config input{background:color-mix(in srgb,#000 60%,transparent);border:1px solid rgba(255,255,255,.2);color:#fff;border-radius:6px;font-size:12px;height:32px;min-height:32px;padding:0 10px}.print-config select:focus,.print-config input:focus{outline:none;border-color:#0ea5e9;box-shadow:0 0 0 2px #0ea5e933}.print-config select{cursor:pointer}.print-config option{background:color-mix(in srgb,#000 98%,transparent)!important;border:none!important}.print-config input{width:60px;text-align:center}.print-config button{background:linear-gradient(147.38deg,#10b981,#047857);color:#fff;border:none;padding:6px 12px;border-radius:4px;font-size:12px;cursor:pointer;transition:all .2s ease}.print-config button:hover{box-shadow:0 4px 12px #10b9814d}.print-config .icon-separator{color:#70706f}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes pulse{0%{box-shadow:0 0 #667eeab3}70%{box-shadow:0 0 0 6px #667eea00}to{box-shadow:0 0 #667eea00}}.compact-icon.active{animation:pulse 2s infinite}@media (max-width: 768px){.toolbox-wrapper{left:.5em;top:8em}:host{padding:8px;min-width:32px}:host.expanded{min-width:280px;padding:10px}.all-tools-container{gap:6px;padding-bottom:4px;-ms-overflow-style:none;scrollbar-width:none}.all-tools-container::-webkit-scrollbar{display:none}.main-tools,.geometry-tools,.measurement-print-tools{gap:4px}.compact-icon{width:28px;height:28px;flex-shrink:0}.measurement-print-tools{padding:3px 6px}::ng-deep .mat-mdc-select-panel{max-width:280px!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:13px!important;min-height:32px!important;padding:6px 12px!important}.print-config{flex-wrap:wrap;justify-content:center}.print-config select,.print-config input{font-size:11px;padding:3px 6px}.print-config input{width:50px}.print-config button{padding:4px 8px;font-size:11px}}@media (max-width: 480px){.toolbox-wrapper{transform-origin:left top}.geometry-tools{gap:4px}.measurement-print-tools{gap:4px;flex-wrap:wrap}.compact-button{font-size:10px;letter-spacing:.2px}.print-config{gap:6px}.print-config select,.print-config input{font-size:10px}.print-config button{flex:1;min-width:60px}}::ng-deep .mat-mdc-simple-snack-bar{background-color:#fff!important}::ng-deep .mat-mdc-tooltip{--mdc-plain-tooltip-container-color: #050505 !important;--mdc-plain-tooltip-supporting-text-color: white !important;border-radius:6px}::ng-deep .mat-mdc-tooltip .mdc-tooltip__surface{background-color:#050505!important;color:#fff!important;border-radius:6px}\n"] }]
2097
+ args: [{ selector: 'map-toolbox', imports: [FormsModule, CommonModule, MatIconModule, MatOptionModule, MatSelectModule, DragDropModule, MatTooltipModule, MatSlideToggleModule], template: "<div class=\"toolbox-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\"\n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\">\n <div class=\"drag-handle-toolbox\" cdkDragHandle>\n <mat-icon>handyman</mat-icon>\n <mat-icon class=\"toggle-icon\" (click)=\"toggleCollapsed($event)\">{{ collapsed ? 'flip_to_front' : 'remove' }}</mat-icon> </div>\n <div class=\"toolbox-container\" [class.collapsed]=\"collapsed\">\n @if(!collapsed) {\n <div class=\"toolbox-content\">\n @if (settings.geometryTypeSettings && settings.geometryTypeSettings.length) {\n <mat-select class=\"geometry-selector\" (selectionChange)=\"settingsChanged($event)\" [(ngModel)]=\"selectedGeometrySetting\" [compareWith]=\"compareGeometrySetting\">\n @for (setting of settings.geometryTypeSettings; track setting) {\n <mat-option [value]=\"setting\">{{setting.typeName}}</mat-option>\n }\n </mat-select> \n }\n <div class=\"all-tools-container\">\n <div class=\"main-tools\">\n @if(!settings?.undoDisabled) {\n <img \n [src]=\"undoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"undo()\" \n matTooltip=\"Fortryd\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Undo\">\n\n <img \n [src]=\"redoIconBase64\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"redo()\" \n matTooltip=\"Gentag\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Redo\">\n }\n <mat-slide-toggle [(ngModel)]=\"snap\" (change)=\"onSnapChange()\">Snap</mat-slide-toggle>\n @if(settings.editEnabled) {\n <img \n [src]=\"editIconBase64\" \n [class.active]=\"activeMode === 'edit'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEdit()\" \n matTooltip=\"Rediger\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Rediger\">\n\n <img \n [src]=\"removePointsIconBase64\" \n [class.active]=\"activeMode === 'edit-remove'\" \n class=\"compact-icon custom-image-icon\"\n (click)=\"startEditRemovePoints()\" \n matTooltip=\"Fjern punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Fjern punkter\">\n }\n @if(settings.cutHoleEnabled) {\n <img \n [src]=\"trimIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'clip-hole'\" \n (click)=\"clipHole()\" \n matTooltip=\"Klip hul\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Klip hul\">\n }\n @if(settings.splitEnabled) {\n <img \n [src]=\"splitIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'split'\"\n (click)=\"split()\" \n matTooltip=\"Sk\u00E6r over\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Sk\u00E6r over\">\n }\n @if(settings.changeTypeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n [class.active]=\"activeMode === 'change-type'\" \n (click)=\"startChangeType()\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Skift type\" \n matTooltipPosition=\"below\">\n find_replace\n </mat-icon>\n }\n @if(settings.mergeEnabled) {\n <mat-icon \n class=\"compact-icon\" \n (click)=\"startMergeFeatures()\" \n matTooltipPosition=\"below\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"Saml flader\" \n [class.active]=\"activeMode === 'merge-features'\">\n merge\n </mat-icon>\n }\n @if(settings.centerPoint) {\n <mat-icon\n (click)=\"setCenterPoint()\"\n matTooltipPosition=\"below\"\n [matTooltipShowDelay]=\"200\"\n matTooltipClass=\"custom-tooltip\"\n [matTooltipHideDelay]=\"300\" \n matTooltip=\"S\u00E6t centerpunkt\" \n [class.active]=\"activeMode === 'center-point'\"\n >adjust</mat-icon>\n }\n </div>\n @if(selectedGeometrySetting && selectedGeometrySetting.availableGeometryTypes?.length) {\n <div class=\"geometry-tools\">\n @for(geomType of selectedGeometrySetting.availableGeometryTypes;track geomType) {\n @if(geomType === 'Polygon') {\n <img \n [src]=\"polygonIconBase64\" \n [class.active]=\"activeMode === 'draw-polygon'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPolygon()\" \n matTooltip=\"Polygon\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Polygon\">\n }\n @if(geomType === 'LineString') {\n <img \n [src]=\"lineStringIconBase64\" \n [class.active]=\"activeMode === 'draw-linestring'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawLineString()\" \n matTooltip=\"LineString\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"LineString\">\n }\n @if(geomType === 'Point') {\n <img \n [src]=\"pointIconBase64\" \n [class.active]=\"activeMode === 'draw-point'\"\n class=\"compact-icon primary custom-image-icon\"\n (click)=\"startDrawPoint()\" \n matTooltip=\"Punkter\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Punkter\">\n }\n }\n <img \n [src]=\"wktIconBase64\" \n class=\"compact-icon secondary custom-image-icon\"\n (click)=\"activateShowInputWKT()\" \n matTooltip=\"WKT\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"WKT\">\n </div>\n }\n <div class=\"tool-separator\" *ngIf=\"deleteEnabled || showMeasureDistance || showMeasureArea || profile.showPrint\"></div>\n <div class=\"measurement-print-tools\">\n <div class=\"measurement-tools\">\n @if (deleteEnabled) {\n <img \n [src]=\"deleteIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'delete'\"\n (click)=\"startDelete()\" \n matTooltip=\"Slet\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Slet\">\n }\n @if (showMeasureDistance) {\n <img \n [src]=\"measureDistanceIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-distance'\"\n (click)=\"startMeasureLength()\" \n matTooltip=\"M\u00E5le afstand\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le afstand\">\n }\n @if(showMeasureArea) {\n <img \n [src]=\"measureAreaIconBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"activeMode === 'measure-area'\"\n (click)=\"startMeasureArea()\" \n matTooltip=\"M\u00E5le areal\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"M\u00E5le areal\">\n }\n </div>\n @if(profile.showPrint) {\n <div class=\"tool-separator print-separator\"></div>\n <div class=\"print-tools\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Print'\"\n (click)=\"startPrintMode()\" \n matTooltip=\"Udskriv\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Udskriv\">\n <img \n [src]=\"drawBase64\" \n class=\"compact-icon custom-image-icon\"\n [class.active]=\"active === 'Draw'\"\n (click)=\"startDrawMode()\" \n matTooltip=\"Tegn\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipClass=\"custom-tooltip\"\n matTooltipPosition=\"below\"\n alt=\"Tegn\">\n </div>\n }\n </div>\n </div>\n @if(showInputWKT) {\n <div class=\"wkt-section\">\n <input class=\"compact-input\" [(ngModel)]=\"WKTString\">\n <div class=\"wkt-actions\">\n <button class=\"compact-button primary\" (click)=\"ReadWKT()\">Indl\u00E6s WKT</button>\n <button class=\"compact-button\" (click)=\"cancelWKT()\">Annuller</button>\n </div>\n </div>\n }\n @if(profile.showPrint) {\n @if(active === \"Print\") {\n <div class=\"print-config\">\n <img \n [src]=\"printBase64\" \n class=\"compact-icon\"\n (click)=\"doPrint()\" \n alt=\"Udskriv\"> \n <span class=\"icon-separator\">i</span>\n <select id=\"formatSelector\" [(ngModel)]=\"format\">\n <option value=\"image/png\" selected>.PNG</option>\n <option value=\"image/jpeg\">.JPG</option>\n </select>\n <select id=\"dimensionSelector\" [(ngModel)]=\"dimId\" (change)=\"handleDimensionSelected()\">\n <option value=\"99\" selected></option>\n <option value=\"0\">1920 X 1080</option>\n <option value=\"1\">1680 X 1050</option>\n <option value=\"2\">1280 X 800</option>\n <option value=\"3\">800 X 600</option>\n </select>\n <input type=\"text\" [(ngModel)]=\"mapWidth\"/> \n <span class=\"icon-separator\">x</span>\n <input type=\"text\" [(ngModel)]=\"mapHeight\"/>\n <button (click)=\"setNewMapDimensions()\">V\u00E6lg</button>\n </div>\n }\n @if(active === \"PrintDraw\") {\n <div class=\"print-draw-config\">\n <span class=\"icon-separator\">Label</span>\n <input type=\"text\" [(ngModel)]=\"printDrawLabel\"/>\n <select id=\"drawToolSelector\" [(ngModel)]=\"printDrawTool\" (change)=\"handlePrintDrawToolChanged()\">\n <option value=\"Arrow\" selected>Pil</option>\n <option value=\"Point\">Punkt</option>\n <option value=\"LineString\">Linje</option>\n <option value=\"Polygon\">Polygon</option>\n <option value=\"Circle\">Cirkel</option>\n <option value=\"Square\">Kvadrat</option>\n <option value=\"Rectangle\">Firkant</option>\n </select>\n <button class=\"compact-button\" (click)=\"handleClearPrintDrawFeatures()\">Ryd</button>\n </div>\n }\n }\n </div>\n }\n </div>\n</div>\n", styles: [".toolbox-wrapper{position:absolute;left:1em;top:31.5em;z-index:1000;cursor:grab;max-width:95vw}.toolbox-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.drag-handle-toolbox{display:flex;align-items:center;justify-content:space-between;background:color-mix(in srgb,#000 60%,transparent);padding:2px 10px;cursor:grab;gap:8px;border-radius:5px 5px 0 0}.drag-handle-toolbox mat-icon{color:#fff;font-size:18px;width:18px;height:18px}.drag-handle-toolbox mat-icon:first-child{flex:1;text-align:left}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:18px!important;width:18px!important;height:18px!important;display:flex;align-items:center;justify-content:center;border-radius:4px;padding:2px;flex-shrink:0}.toggle-icon:hover{color:#fff;background:#ffffff26}.toggle-icon:active{background:#ffffff40}:host{position:relative;display:flex;justify-content:center}:host.expanded{width:auto;min-width:320px;padding:12px}.toolbox-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;padding:10px;width:auto;min-width:32px;transition:all .3s ease;cursor:default;border-radius:0 0 5px 5px}.toolbox-container.collapsed{display:none}.toolbox-content{display:flex;flex-direction:column;width:100%;gap:3px;animation:slideDown .3s cubic-bezier(.4,0,.2,1)}.all-tools-container{display:flex;flex-direction:row;align-items:center;flex-wrap:nowrap;width:100%;justify-content:flex-start;overflow-x:hidden}.all-tools-container::-webkit-scrollbar{height:4px}.all-tools-container::-webkit-scrollbar-thumb{background:#ccc;border-radius:2px}.main-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.main-tools ::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:12px;font-weight:500;color:#fff}.geometry-selector{width:100%}.geometry-selector ::ng-deep .mat-mdc-select{font-size:14px;line-height:1.4;border-radius:6px}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:32px;min-height:32px;padding:0 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);transition:all .2s ease}.geometry-selector ::ng-deep .mat-mdc-select-trigger:hover{background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:14px;font-weight:500;color:#fff}.geometry-selector ::ng-deep .mat-mdc-select-arrow-wrapper{height:16px;transform:scale(.85)}.geometry-selector ::ng-deep .mat-mdc-form-field-infix{min-height:32px;padding:6px 0}.geometry-selector ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mat-mdc-select-panel{min-width:fit-content!important;max-width:320px!important;background:color-mix(in srgb,#000 100%,transparent)!important;border:none!important;border-radius:8px!important;box-shadow:0 8px 24px #0000001f,0 2px 6px #00000014!important;margin-top:6px!important;padding:4px 0!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:14px!important;min-height:36px!important;padding:8px 14px!important;transition:all .15s ease!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option:hover:not(.mat-mdc-option-disabled){background:#444849!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option.mat-active{background:color-mix(in srgb,#000 60%,transparent)!important;color:#fff!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px!important;font-weight:500!important;color:#fff!important}::ng-deep .cdk-overlay-pane{z-index:1001}::ng-deep .cdk-overlay-backdrop{z-index:1000}.geometry-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap;background:color-mix(in srgb,#000 20%,transparent);border-radius:8px;padding:4px 8px;border:1px solid rgba(255,255,255,.1)}.measurement-tools,.print-tools{display:flex;flex-direction:row;align-items:center;gap:6px;flex-wrap:nowrap}.measurement-tools .compact-icon,.print-tools .compact-icon{transition:all .3s cubic-bezier(.4,0,.2,1)}.measurement-tools .compact-icon.custom-image-icon,.print-tools .compact-icon.custom-image-icon{padding:4px;background:none;border:1px solid rgba(255,255,255,.2)}.measurement-tools .compact-icon.custom-image-icon img,.print-tools .compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:filter .2s ease}.measurement-tools .compact-icon.custom-image-icon.active,.print-tools .compact-icon.custom-image-icon.active{background:linear-gradient(147.38deg,#0ea5e9,#075985);border-color:transparent;box-shadow:0 4px 12px #0ea5e966}.measurement-tools .compact-icon.custom-image-icon.active img,.print-tools .compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1)}.measurement-tools .compact-icon.custom-image-icon.active:hover,.print-tools .compact-icon.custom-image-icon.active:hover{box-shadow:0 6px 20px #0ea5e980}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active),.print-tools .compact-icon.custom-image-icon:hover:not(.active){background:color-mix(in srgb,#000 70%,transparent);border-color:#0ea5e9;box-shadow:0 2px 8px #0ea5e94d}.measurement-tools .compact-icon.custom-image-icon:hover:not(.active) img,.print-tools .compact-icon.custom-image-icon:hover:not(.active) img{filter:brightness(0) invert(.8)}.print-tools .compact-icon{background:linear-gradient(147.38deg,#4f46e5,#3730a3);color:#fff;border:1px solid rgba(255,255,255,.2)}.print-tools .compact-icon.print-icon{background:linear-gradient(147.38deg,#10b981,#047857)}.print-tools .compact-icon.draw-icon{background:linear-gradient(147.38deg,#f59e0b,#d97706)}.print-tools .compact-icon.active{background:linear-gradient(147.38deg,#ef4444,#dc2626);box-shadow:0 4px 12px #ef444466;border-color:transparent;transform:scale(1.05)}.print-tools .compact-icon.active:hover{box-shadow:0 6px 20px #ef444480;transform:scale(1.08)}.print-tools .compact-icon:hover:not(.active){box-shadow:0 4px 12px #0000004d;opacity:.9}.tool-separator{width:1px;height:24px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.3),transparent);margin:0 4px}.tool-separator.print-separator{height:28px;background:linear-gradient(to bottom,transparent,rgba(255,255,255,.5),transparent)}.compact-icon{cursor:pointer;color:#fff;transition:all .3s cubic-bezier(.4,0,.2,1);width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;background:color-mix(in srgb,#000 40%,transparent);border:1px solid rgba(255,255,255,.2);box-shadow:0 1px 2px #0000001a;flex-shrink:0}.compact-icon.active{color:#fff;background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent;box-shadow:0 8px 25px #667eea4d;transform:scale(1.05)}.compact-icon.active:hover{box-shadow:0 12px 35px #667eea66;transform:scale(1.08)}.compact-icon:hover:not(.active){color:#fff;background:color-mix(in srgb,#000 70%,transparent);border-color:#667eea;box-shadow:0 4px 12px #0003}.compact-icon.custom-image-icon{padding:0;background:none;border:none}.compact-icon.custom-image-icon img{width:100%;height:100%;object-fit:contain;transition:transform .2s ease}.compact-icon.custom-image-icon.active{background:linear-gradient(135deg,#667eea,#764ba2);border-color:transparent}.compact-icon.custom-image-icon.active img{filter:brightness(0) invert(1);transform:scale(1.1)}.compact-icon.custom-image-icon:hover:not(.active) img{transform:scale(1.05)}.wkt-section{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid rgba(255,255,255,.1);animation:fadeIn .2s ease}.wkt-actions{display:flex;gap:6px;justify-content:space-between}.compact-button{padding:6px 10px;border:none;border-radius:6px;background:color-mix(in srgb,#000 60%,transparent);color:#fff;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);text-transform:uppercase;letter-spacing:.4px;min-height:32px;display:flex;align-items:center;justify-content:center;flex:1;box-shadow:0 1px 2px #0000000d}.compact-button.primary.active{background:linear-gradient(135deg,#667eea,#764ba2);box-shadow:0 8px 25px #667eea4d;color:#fff}.compact-button.primary.active:hover{box-shadow:0 12px 35px #667eea66}.compact-button.secondary{background:color-mix(in srgb,#000 20%,transparent);color:#fff}.compact-button.secondary:hover{background:color-mix(in srgb,#5a6268 60%,transparent)}.compact-input{padding:8px 10px;border:none;border-radius:6px;font-size:13px;transition:all .2s ease;background:color-mix(in srgb,#000 60%,transparent);color:#fff}.compact-input:focus{outline:none;border-color:#1976d2;background:color-mix(in srgb,#000 70%,transparent);box-shadow:0 0 0 3px #1976d233}.print-config,.print-draw-config{display:flex;align-items:center;gap:8px;padding:5px;background:color-mix(in srgb,#000 40%,transparent);border-radius:8px;border:1px solid rgba(255,255,255,.1);animation:slideDown .3s ease}.print-config select,.print-config input,.print-draw-config select,.print-draw-config input{background:color-mix(in srgb,#000 60%,transparent);border:1px solid rgba(255,255,255,.2);color:#fff;border-radius:6px;font-size:12px;height:32px;min-height:32px;padding:0 10px}.print-config select:focus,.print-config input:focus,.print-draw-config select:focus,.print-draw-config input:focus{outline:none;border-color:#0ea5e9;box-shadow:0 0 0 2px #0ea5e933}.print-config select,.print-draw-config select{cursor:pointer}.print-config option,.print-draw-config option{background:color-mix(in srgb,#000 98%,transparent)!important;border:none!important}.print-config input,.print-draw-config input{width:60px;text-align:center}.print-config button,.print-draw-config button{background:linear-gradient(147.38deg,#10b981,#047857);color:#fff;border:none;padding:6px 12px;border-radius:4px;font-size:12px;cursor:pointer;transition:all .2s ease}.print-config button:hover,.print-draw-config button:hover{box-shadow:0 4px 12px #10b9814d}.print-config .icon-separator,.print-draw-config .icon-separator{color:#fff}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes pulse{0%{box-shadow:0 0 #667eeab3}70%{box-shadow:0 0 0 6px #667eea00}to{box-shadow:0 0 #667eea00}}.compact-icon.active{animation:pulse 2s infinite}@media (max-width: 768px){.toolbox-wrapper{left:.5em;top:8em;max-width:calc(100vw - 2.5em)}.drag-handle-toolbox{padding:3px 6px;gap:6px}.drag-handle-toolbox mat-icon{font-size:16px;width:16px;height:16px}.toggle-icon{font-size:16px!important;width:16px!important;height:16px!important}.toolbox-container{padding:8px;min-width:28px;max-width:calc(100vw - 3em)}:host{padding:8px;min-width:32px}:host.expanded{min-width:280px;padding:10px}.all-tools-container{flex-wrap:wrap;gap:6px;max-height:50vh;overflow-y:auto;padding:0;-ms-overflow-style:none;scrollbar-width:none}.all-tools-container::-webkit-scrollbar{display:none}.main-tools,.geometry-tools,.measurement-print-tools,.print-tools{display:flex;flex-wrap:wrap;justify-content:center;gap:4px}.compact-icon{width:28px;height:28px;flex-shrink:0}.measurement-print-tools{padding:3px 6px}.geometry-selector{width:100%;margin-bottom:8px}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:28px;min-height:28px;padding:0 8px;font-size:12px}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:12px}::ng-deep .mat-mdc-select-panel{max-width:calc(100vw - 2em)!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:13px!important;min-height:32px!important;padding:6px 12px!important}.print-config,.print-draw-config{flex-direction:column;align-items:stretch;gap:6px}.print-config select,.print-config input,.print-draw-config select,.print-draw-config input{font-size:11px;padding:4px 8px;height:28px;min-height:28px}.print-config input,.print-draw-config input{width:50px}.print-config button,.print-draw-config button{padding:4px 8px;font-size:11px;height:28px}.wkt-section .compact-input{font-size:12px;padding:6px 8px}.wkt-section .compact-button{font-size:11px;padding:5px 8px;min-height:28px}::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:11px!important}}@media (max-width: 480px){.toolbox-wrapper{left:.25em;top:6em;transform-origin:left top;max-width:calc(100vw - .5em)}.drag-handle-toolbox{padding:2px 4px;gap:4px}.drag-handle-toolbox mat-icon{font-size:14px;width:14px;height:14px}.toggle-icon{font-size:14px!important;width:14px!important;height:14px!important}.toolbox-container{padding:6px;min-width:24px}.toolbox-content{gap:8px}.all-tools-container{flex-direction:row;align-items:center;max-height:60vh}.main-tools,.geometry-tools{gap:3px;flex-wrap:wrap;justify-content:center}.measurement-print-tools{gap:3px;flex-wrap:wrap;padding:2px 4px;width:100%;justify-content:center}.measurement-tools,.print-tools{gap:3px}.compact-icon{width:26px;height:26px}.tool-separator{display:none}.geometry-selector ::ng-deep .mat-mdc-select-trigger{height:26px;min-height:26px;padding:0 6px;font-size:11px}.geometry-selector ::ng-deep .mat-mdc-select-value{font-size:11px}.compact-button{font-size:10px;letter-spacing:.2px;padding:4px 6px;min-height:26px}.compact-input{font-size:11px;padding:4px 6px}.print-config,.print-draw-config{gap:4px;padding:6px}.print-config select,.print-config input,.print-draw-config select,.print-draw-config input{font-size:10px;height:26px;min-height:26px;padding:2px 6px}.print-config input,.print-draw-config input{width:45px}.print-config button,.print-draw-config button{flex:1;min-width:60px;font-size:10px;padding:3px 6px;height:26px}.print-config .icon-separator,.print-draw-config .icon-separator{font-size:10px}.wkt-section{gap:6px;padding-top:8px}::ng-deep .mat-mdc-slide-toggle{transform:scale(.9)}::ng-deep .mat-mdc-slide-toggle .mdc-label{font-size:10px!important}::ng-deep .mat-mdc-select-panel{max-width:calc(100vw - 1em)!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option{font-size:12px!important;min-height:28px!important;padding:4px 10px!important}}::ng-deep .mat-mdc-simple-snack-bar{background-color:#fff!important}::ng-deep .mat-mdc-tooltip{--mdc-plain-tooltip-container-color: #050505 !important;--mdc-plain-tooltip-supporting-text-color: white !important;border-radius:6px}::ng-deep .mat-mdc-tooltip .mdc-tooltip__surface{background-color:#050505!important;color:#fff!important;border-radius:6px}\n"] }]
1672
2098
  }], ctorParameters: () => [], propDecorators: { map: [{
1673
2099
  type: Input,
1674
2100
  args: [{ required: true }]
@@ -1692,12 +2118,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1692
2118
 
1693
2119
  class ActiveObjectsComponent {
1694
2120
  _drawLayerService = inject(DrawLayerSourceService);
2121
+ _centerPointService = inject(CenterPointService);
2122
+ _undoRedo = inject(UndoRedoService);
1695
2123
  features$ = this._drawLayerService.features$;
1696
2124
  collapsed = false;
1697
2125
  settings;
1698
2126
  activeFeatures = [];
1699
2127
  _featureHelper = inject(FeatureHelperService);
1700
- _highlight = inject(highlightService);
2128
+ _highlight = inject(HighlightService);
1701
2129
  _zoomService = inject(ZoomService);
1702
2130
  opacity = 1;
1703
2131
  dragPosition = { x: 0, y: 0 };
@@ -1711,7 +2139,12 @@ class ActiveObjectsComponent {
1711
2139
  .map(ft => ({ featureType: ft,
1712
2140
  display: this.settings.geometryTypeSettings.find(gts => gts.typeId === ft).typeName,
1713
2141
  features: features.filter(f => this._featureHelper.typeId(f) === ft)
1714
- .map(f => ({ id: f.getId(), feature: f, locked: this._featureHelper.isLocked(f), area: this._getAreaString(f) })) }));
2142
+ .map(f => ({
2143
+ id: f.getId(),
2144
+ feature: f,
2145
+ locked: this._featureHelper.isLocked(f),
2146
+ area: this._getAreaString(f)
2147
+ })) }));
1715
2148
  this.activeFeatures = [...featuresObj];
1716
2149
  }
1717
2150
  });
@@ -1725,10 +2158,13 @@ class ActiveObjectsComponent {
1725
2158
  }
1726
2159
  return this.settings.sizeInHa ? `(${(getArea(feature.getGeometry()) / 10000).toFixed(2)} ha)` : `(${getArea(feature.getGeometry()).toFixed(2)} m2)`;
1727
2160
  }
2161
+ reset() {
2162
+ this._undoRedo.reset();
2163
+ this.highlightedId = null;
2164
+ this._highlight.clear();
2165
+ this.zoomToAll();
2166
+ }
1728
2167
  zoomToAll() {
1729
- const formatter = new GeoJSON({ dataProjection: 'EPSG:25832', featureProjection: 'EPSG:25832' });
1730
- const allTheFeatures = formatter.writeFeaturesObject(this._drawLayerService.allFeatures);
1731
- console.log("🚀 ~ ActiveObjectsComponent ~ zoomToAll ~ allTheFeatures:", JSON.stringify(allTheFeatures));
1732
2168
  this._zoomService.zoomToFeatures(this._drawLayerService.allFeatures);
1733
2169
  }
1734
2170
  highlight(id) {
@@ -1749,6 +2185,7 @@ class ActiveObjectsComponent {
1749
2185
  }
1750
2186
  delete(id) {
1751
2187
  this._drawLayerService.remove(id);
2188
+ this._centerPointService.handleFeatureDeleted(id);
1752
2189
  this._highlight.clear();
1753
2190
  }
1754
2191
  togglePanel() {
@@ -1780,33 +2217,158 @@ class ActiveObjectsComponent {
1780
2217
  }
1781
2218
  }
1782
2219
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ActiveObjectsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1783
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ActiveObjectsComponent, isStandalone: true, selector: "activeObjects", inputs: { settings: "settings" }, ngImport: i0, template: "<div class=\"active-objects-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle-active-objects\" cdkDragHandle>\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">drag_indicator</mat-icon> \n </div>\n <div class=\"active-objects-container\">\n <div class=\"panel-header\">\n <h4>Aktive flader</h4>\n <mat-icon class=\"toggle-icon\" (click)=\"togglePanel()\">\n {{ collapsed ? 'expand_more' : 'expand_less' }}\n </mat-icon>\n </div>\n @if(!collapsed) {\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"opacity\"\n (input)=\"updateOpacity()\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n }\n\n @if(!collapsed) {\n <div class=\"active-objects-content\">\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">highlight</mat-icon>\n @for(featureTypeObj of activeFeatures; track featureTypeObj.featureType) {\n <mat-expansion-panel>\n <mat-expansion-panel-header \n [matTooltip]=\"featureTypeObj.display\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"right\">\n <span class=\"panel-title\">\n {{featureTypeObj.display}} ({{featureTypeObj.features.length}})\n </span>\n </mat-expansion-panel-header>\n <div class=\"item-list\">\n @for(item of featureTypeObj.features; track item.id) {\n <div class=\"item\">\n <div class=\"item-text\">\n <span class=\"item-id\">{{item.id}}</span>\n <span class=\"item-area\">{{item.area}}</span>\n </div>\n <mat-icon *ngIf=\"!item.locked\" (click)=\"delete(item.id)\">delete</mat-icon>\n <mat-icon (click)=\"highlight(item.id)\" [class.highlight-active]=\"highlightedId === item.id\">highlight</mat-icon>\n </div>\n }\n </div>\n </mat-expansion-panel>\n }\n </div>\n }\n </div> \n</div>", styles: ["@charset \"UTF-8\";.active-objects-wrapper{position:absolute;top:8em;left:1em;z-index:1000;cursor:grab;border-radius:8px;box-shadow:0 2px 10px #0000001a;background:color-mix(in srgb,#000 60%,transparent);width:fit-content;max-width:295px;transition:width .3s ease}.active-objects-wrapper.collapsed{width:120px;max-width:150px}.active-objects-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .panel-title{display:block;overflow:visible;text-overflow:clip;white-space:normal;max-width:220px;margin-right:10px;line-height:1.3;word-break:break-word}.item{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-radius:4px;background:color-mix(in srgb,#000 60%,transparent)!important;transition:all .2s ease;font-size:14px;color:#fff;min-height:40px;cursor:default}.item .item-text{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden}.item .item-id{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-bottom:2px}.item .item-area{font-size:12px;color:#ccc;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item mat-icon{cursor:pointer;color:#f44336;font-size:18px;width:18px;height:18px;flex-shrink:0;margin-left:8px;transition:color .2s ease,background .2s ease}.item mat-icon:hover{color:#d32f2f}.highlight-active{color:#4caf50!important;text-shadow:0 0 6px #4caf50;transform:scale(1.1);transition:all .2s ease}.drag-handle-active-objects{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 0%,transparent);border-radius:8px 8px 0 0;padding:4px;cursor:grab}.drag-handle-active-objects mat-icon{color:#fff;font-size:18px;width:18px;height:18px}.active-objects-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;transition:all .3s ease;cursor:default;box-sizing:border-box}.active-objects-container .panel-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:5px;cursor:default}.active-objects-container .panel-header h4{margin:0;padding:5px;background:transparent;font-weight:600;color:#fff;flex:1;font-size:16px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .panel-header .toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:22px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:6px;flex-shrink:0;margin:0}.active-objects-container .panel-header .toggle-icon:hover{color:#ffffffb3;background:#1976d214}.active-objects-container .collapsed-title{color:#fff;font-weight:600;font-size:12px;padding:8px 4px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .collapsed-title:hover{color:#1976d2}.active-objects-content{display:block;max-height:278px;overflow:auto}.active-objects-content::-webkit-scrollbar{width:8px;border-radius:10px;border:5px solid transparent}.active-objects-content::-webkit-scrollbar-thumb{background:#0000004d;border:5px solid transparent;border-radius:10px;background-clip:padding-box}.active-objects-content::-webkit-scrollbar-thumb:hover{background:#0006;background-clip:padding-box;border:3px solid transparent}.active-objects-content .zoom-icon{color:#4caf50!important;border-radius:50%;padding:6px;margin:4px;cursor:pointer;transition:all .3s ease;font-size:20px;width:20px;height:20px}.active-objects-content .zoom-icon:hover{background:#4caf5033!important}mat-expansion-panel{border-radius:0!important;box-shadow:none!important}mat-expansion-panel:last-child{border-bottom:none}mat-expansion-panel ::ng-deep .mat-expansion-panel-header{padding:0 16px;font-weight:500}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .mat-content{display:flex;justify-content:space-between;align-items:center;color:#fff}mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding:0}.item-list{display:flex;flex-direction:column;gap:4px;padding:8px;max-height:300px;overflow-y:auto}.item-list::-webkit-scrollbar{width:6px}.item-list::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.item-list::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.item-list::-webkit-scrollbar-thumb:hover{background:#a8a8a8}@media (max-width: 768px){.active-objects-wrapper{right:.5em;top:8em;max-width:280px;width:280px}.item{font-size:13px;padding:6px 10px}}@media (max-width: 480px){.active-objects-wrapper{right:.5em;left:.5em;max-width:calc(100vw - 1em);width:auto}.item-list{max-height:200px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
2220
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ActiveObjectsComponent, isStandalone: true, selector: "activeObjects", inputs: { settings: "settings" }, ngImport: i0, template: "<div class=\"active-objects-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle-active-objects\" cdkDragHandle>\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">dynamic_form</mat-icon>\n <mat-icon class=\"toggle-icon\" (click)=\"togglePanel()\">\n {{ collapsed ? 'flip_to_front' : 'remove' }}\n </mat-icon>\n </div>\n <div class=\"active-objects-container\">\n @if(!collapsed) {\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"opacity\"\n (input)=\"updateOpacity()\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n }\n\n @if(!collapsed) {\n <div class=\"active-objects-content\">\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">highlight</mat-icon>\n <mat-icon (click)=\"reset()\">replay</mat-icon>\n @for(featureTypeObj of activeFeatures; track featureTypeObj.featureType) {\n <mat-expansion-panel>\n <mat-expansion-panel-header \n [matTooltip]=\"featureTypeObj.display\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"right\">\n <span class=\"panel-title\">\n {{featureTypeObj.display}} ({{featureTypeObj.features.length}})\n </span>\n </mat-expansion-panel-header>\n <div class=\"item-list\">\n @for(item of featureTypeObj.features; track item.id) {\n <div class=\"item\">\n <div class=\"item-text\">\n <span class=\"item-id\">{{item.id}}</span>\n <span class=\"item-area\">{{item.area}}</span>\n </div>\n @if(!item.locked) {\n <mat-icon (click)=\"delete(item.id)\">delete</mat-icon>\n }\n <mat-icon (click)=\"highlight(item.id)\" [class.highlight-active]=\"highlightedId === item.id\">highlight</mat-icon>\n </div>\n }\n </div>\n </mat-expansion-panel>\n }\n </div>\n }\n </div> \n</div>", styles: ["@charset \"UTF-8\";.active-objects-wrapper{position:absolute;top:15em;left:1em;z-index:1000;cursor:grab;box-shadow:0 2px 10px #0000001a;background:color-mix(in srgb,#000 60%,transparent);width:fit-content;max-width:295px;transition:width .3s ease;border-radius:5px 5px 0 0}.active-objects-wrapper.collapsed{width:70px;max-width:150px}.active-objects-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .panel-title{display:block;overflow:visible;text-overflow:clip;white-space:normal;max-width:220px;margin-right:10px;line-height:1.3;word-break:break-word}.item{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-radius:4px;background:color-mix(in srgb,#000 60%,transparent)!important;transition:all .2s ease;font-size:14px;color:#fff;min-height:40px;cursor:default}.item .item-text{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden}.item .item-id{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-bottom:2px}.item .item-area{font-size:12px;color:#ccc;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item mat-icon{cursor:pointer;color:#f44336;font-size:18px;width:18px;height:18px;flex-shrink:0;margin-left:8px;transition:color .2s ease,background .2s ease}.item mat-icon:hover{color:#d32f2f}.highlight-active{color:#4caf50!important;text-shadow:0 0 6px #4caf50;transform:scale(1.1);transition:all .2s ease}.drag-handle-active-objects{display:flex;align-items:center;justify-content:space-between;background:color-mix(in srgb,#000 0%,transparent);padding:4px 8px;cursor:grab}.drag-handle-active-objects .zoom-icon{color:#fff;font-size:18px;width:18px;height:18px}.drag-handle-active-objects .toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:18px!important;width:18px!important;height:18px!important;display:flex;align-items:center;justify-content:center;border-radius:4px;padding:2px;flex-shrink:0}.drag-handle-active-objects .toggle-icon:hover{color:#fff;background:#ffffff26}.active-objects-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;transition:all .3s ease;cursor:default;box-sizing:border-box}.active-objects-container .panel-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:5px;cursor:default}.active-objects-container .panel-header h4{margin:0;padding:5px;background:transparent;font-weight:600;color:#fff;flex:1;font-size:16px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .collapsed-title{color:#fff;font-weight:600;font-size:12px;padding:8px 4px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .collapsed-title:hover{color:#1976d2}.active-objects-content{display:block;max-height:278px;overflow:auto}.active-objects-content::-webkit-scrollbar{width:12px}.active-objects-content::-webkit-scrollbar-track{background:#757474;border-radius:8px}.active-objects-content::-webkit-scrollbar-thumb{background:#1a1c1f;border-radius:8px;border:2px solid #2a2c30}.active-objects-content::-webkit-scrollbar-thumb:hover{background:#0f1012}.active-objects-content::-webkit-scrollbar-button{width:12px;height:16px;background:#2a2c30;border:1px solid #1a1c1f}.active-objects-content::-webkit-scrollbar-button:vertical:decrement{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 4l-4 4h8z'/%3E%3C/svg%3E\") no-repeat center;border-radius:8px 8px 0 0}.active-objects-content::-webkit-scrollbar-button:vertical:decrement:hover{background-color:#1a1c1f}.active-objects-content::-webkit-scrollbar-button:vertical:increment{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 8l4-4H2z'/%3E%3C/svg%3E\") no-repeat center;border-radius:0 0 8px 8px}.active-objects-content::-webkit-scrollbar-button:vertical:increment:hover{background-color:#1a1c1f}.active-objects-content .zoom-icon{color:#4caf50!important;border-radius:50%;padding:6px;margin:4px;cursor:pointer;transition:all .3s ease;font-size:20px;width:20px;height:20px}.active-objects-content .zoom-icon:hover{background:#4caf5033!important}mat-expansion-panel{border-radius:0!important;box-shadow:none!important}mat-expansion-panel:last-child{border-bottom:none}mat-expansion-panel ::ng-deep .mat-expansion-panel-header{padding:0 16px;font-weight:500}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .mat-content{display:flex;justify-content:space-between;align-items:center;color:#fff}mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding:0}.item-list{display:flex;flex-direction:column;gap:4px;padding:8px;max-height:300px;overflow-y:auto}.item-list::-webkit-scrollbar{width:6px}.item-list::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.item-list::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.item-list::-webkit-scrollbar-thumb:hover{background:#a8a8a8}@media (max-width: 768px){.active-objects-wrapper{right:.5em;top:8em;max-width:280px;width:280px}.item{font-size:13px;padding:6px 10px}}@media (max-width: 480px){.active-objects-wrapper{right:.5em;left:.5em;max-width:calc(100vw - 1em);width:auto}.item-list{max-height:200px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
1784
2221
  }
1785
2222
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ActiveObjectsComponent, decorators: [{
1786
2223
  type: Component,
1787
- args: [{ selector: 'activeObjects', imports: [CommonModule, FormsModule, MatExpansionModule, MatIconModule, DragDropModule, MatTooltipModule], template: "<div class=\"active-objects-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle-active-objects\" cdkDragHandle>\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">drag_indicator</mat-icon> \n </div>\n <div class=\"active-objects-container\">\n <div class=\"panel-header\">\n <h4>Aktive flader</h4>\n <mat-icon class=\"toggle-icon\" (click)=\"togglePanel()\">\n {{ collapsed ? 'expand_more' : 'expand_less' }}\n </mat-icon>\n </div>\n @if(!collapsed) {\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"opacity\"\n (input)=\"updateOpacity()\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n }\n\n @if(!collapsed) {\n <div class=\"active-objects-content\">\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">highlight</mat-icon>\n @for(featureTypeObj of activeFeatures; track featureTypeObj.featureType) {\n <mat-expansion-panel>\n <mat-expansion-panel-header \n [matTooltip]=\"featureTypeObj.display\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"right\">\n <span class=\"panel-title\">\n {{featureTypeObj.display}} ({{featureTypeObj.features.length}})\n </span>\n </mat-expansion-panel-header>\n <div class=\"item-list\">\n @for(item of featureTypeObj.features; track item.id) {\n <div class=\"item\">\n <div class=\"item-text\">\n <span class=\"item-id\">{{item.id}}</span>\n <span class=\"item-area\">{{item.area}}</span>\n </div>\n <mat-icon *ngIf=\"!item.locked\" (click)=\"delete(item.id)\">delete</mat-icon>\n <mat-icon (click)=\"highlight(item.id)\" [class.highlight-active]=\"highlightedId === item.id\">highlight</mat-icon>\n </div>\n }\n </div>\n </mat-expansion-panel>\n }\n </div>\n }\n </div> \n</div>", styles: ["@charset \"UTF-8\";.active-objects-wrapper{position:absolute;top:8em;left:1em;z-index:1000;cursor:grab;border-radius:8px;box-shadow:0 2px 10px #0000001a;background:color-mix(in srgb,#000 60%,transparent);width:fit-content;max-width:295px;transition:width .3s ease}.active-objects-wrapper.collapsed{width:120px;max-width:150px}.active-objects-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .panel-title{display:block;overflow:visible;text-overflow:clip;white-space:normal;max-width:220px;margin-right:10px;line-height:1.3;word-break:break-word}.item{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-radius:4px;background:color-mix(in srgb,#000 60%,transparent)!important;transition:all .2s ease;font-size:14px;color:#fff;min-height:40px;cursor:default}.item .item-text{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden}.item .item-id{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-bottom:2px}.item .item-area{font-size:12px;color:#ccc;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item mat-icon{cursor:pointer;color:#f44336;font-size:18px;width:18px;height:18px;flex-shrink:0;margin-left:8px;transition:color .2s ease,background .2s ease}.item mat-icon:hover{color:#d32f2f}.highlight-active{color:#4caf50!important;text-shadow:0 0 6px #4caf50;transform:scale(1.1);transition:all .2s ease}.drag-handle-active-objects{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 0%,transparent);border-radius:8px 8px 0 0;padding:4px;cursor:grab}.drag-handle-active-objects mat-icon{color:#fff;font-size:18px;width:18px;height:18px}.active-objects-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;transition:all .3s ease;cursor:default;box-sizing:border-box}.active-objects-container .panel-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:5px;cursor:default}.active-objects-container .panel-header h4{margin:0;padding:5px;background:transparent;font-weight:600;color:#fff;flex:1;font-size:16px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .panel-header .toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:22px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:6px;flex-shrink:0;margin:0}.active-objects-container .panel-header .toggle-icon:hover{color:#ffffffb3;background:#1976d214}.active-objects-container .collapsed-title{color:#fff;font-weight:600;font-size:12px;padding:8px 4px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .collapsed-title:hover{color:#1976d2}.active-objects-content{display:block;max-height:278px;overflow:auto}.active-objects-content::-webkit-scrollbar{width:8px;border-radius:10px;border:5px solid transparent}.active-objects-content::-webkit-scrollbar-thumb{background:#0000004d;border:5px solid transparent;border-radius:10px;background-clip:padding-box}.active-objects-content::-webkit-scrollbar-thumb:hover{background:#0006;background-clip:padding-box;border:3px solid transparent}.active-objects-content .zoom-icon{color:#4caf50!important;border-radius:50%;padding:6px;margin:4px;cursor:pointer;transition:all .3s ease;font-size:20px;width:20px;height:20px}.active-objects-content .zoom-icon:hover{background:#4caf5033!important}mat-expansion-panel{border-radius:0!important;box-shadow:none!important}mat-expansion-panel:last-child{border-bottom:none}mat-expansion-panel ::ng-deep .mat-expansion-panel-header{padding:0 16px;font-weight:500}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .mat-content{display:flex;justify-content:space-between;align-items:center;color:#fff}mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding:0}.item-list{display:flex;flex-direction:column;gap:4px;padding:8px;max-height:300px;overflow-y:auto}.item-list::-webkit-scrollbar{width:6px}.item-list::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.item-list::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.item-list::-webkit-scrollbar-thumb:hover{background:#a8a8a8}@media (max-width: 768px){.active-objects-wrapper{right:.5em;top:8em;max-width:280px;width:280px}.item{font-size:13px;padding:6px 10px}}@media (max-width: 480px){.active-objects-wrapper{right:.5em;left:.5em;max-width:calc(100vw - 1em);width:auto}.item-list{max-height:200px}}\n"] }]
2224
+ args: [{ selector: 'activeObjects', imports: [CommonModule, FormsModule, MatExpansionModule, MatIconModule, DragDropModule, MatTooltipModule], template: "<div class=\"active-objects-wrapper\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle-active-objects\" cdkDragHandle>\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">dynamic_form</mat-icon>\n <mat-icon class=\"toggle-icon\" (click)=\"togglePanel()\">\n {{ collapsed ? 'flip_to_front' : 'remove' }}\n </mat-icon>\n </div>\n <div class=\"active-objects-container\">\n @if(!collapsed) {\n <input \n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n [(ngModel)]=\"opacity\"\n (input)=\"updateOpacity()\"\n (mousedown)=\"stopDrag($event)\"\n (touchstart)=\"stopDrag($event)\"\n (pointerdown)=\"stopDrag($event)\"\n >\n }\n\n @if(!collapsed) {\n <div class=\"active-objects-content\">\n <mat-icon class=\"zoom-icon\" (click)=\"zoomToAll()\">highlight</mat-icon>\n <mat-icon (click)=\"reset()\">replay</mat-icon>\n @for(featureTypeObj of activeFeatures; track featureTypeObj.featureType) {\n <mat-expansion-panel>\n <mat-expansion-panel-header \n [matTooltip]=\"featureTypeObj.display\" \n [matTooltipShowDelay]=\"200\"\n [matTooltipHideDelay]=\"300\" \n matTooltipPosition=\"right\">\n <span class=\"panel-title\">\n {{featureTypeObj.display}} ({{featureTypeObj.features.length}})\n </span>\n </mat-expansion-panel-header>\n <div class=\"item-list\">\n @for(item of featureTypeObj.features; track item.id) {\n <div class=\"item\">\n <div class=\"item-text\">\n <span class=\"item-id\">{{item.id}}</span>\n <span class=\"item-area\">{{item.area}}</span>\n </div>\n @if(!item.locked) {\n <mat-icon (click)=\"delete(item.id)\">delete</mat-icon>\n }\n <mat-icon (click)=\"highlight(item.id)\" [class.highlight-active]=\"highlightedId === item.id\">highlight</mat-icon>\n </div>\n }\n </div>\n </mat-expansion-panel>\n }\n </div>\n }\n </div> \n</div>", styles: ["@charset \"UTF-8\";.active-objects-wrapper{position:absolute;top:15em;left:1em;z-index:1000;cursor:grab;box-shadow:0 2px 10px #0000001a;background:color-mix(in srgb,#000 60%,transparent);width:fit-content;max-width:295px;transition:width .3s ease;border-radius:5px 5px 0 0}.active-objects-wrapper.collapsed{width:70px;max-width:150px}.active-objects-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .panel-title{display:block;overflow:visible;text-overflow:clip;white-space:normal;max-width:220px;margin-right:10px;line-height:1.3;word-break:break-word}.item{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-radius:4px;background:color-mix(in srgb,#000 60%,transparent)!important;transition:all .2s ease;font-size:14px;color:#fff;min-height:40px;cursor:default}.item .item-text{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden}.item .item-id{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-bottom:2px}.item .item-area{font-size:12px;color:#ccc;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item mat-icon{cursor:pointer;color:#f44336;font-size:18px;width:18px;height:18px;flex-shrink:0;margin-left:8px;transition:color .2s ease,background .2s ease}.item mat-icon:hover{color:#d32f2f}.highlight-active{color:#4caf50!important;text-shadow:0 0 6px #4caf50;transform:scale(1.1);transition:all .2s ease}.drag-handle-active-objects{display:flex;align-items:center;justify-content:space-between;background:color-mix(in srgb,#000 0%,transparent);padding:4px 8px;cursor:grab}.drag-handle-active-objects .zoom-icon{color:#fff;font-size:18px;width:18px;height:18px}.drag-handle-active-objects .toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:18px!important;width:18px!important;height:18px!important;display:flex;align-items:center;justify-content:center;border-radius:4px;padding:2px;flex-shrink:0}.drag-handle-active-objects .toggle-icon:hover{color:#fff;background:#ffffff26}.active-objects-container{display:flex;flex-direction:column;align-items:center;width:100%;gap:10px;transition:all .3s ease;cursor:default;box-sizing:border-box}.active-objects-container .panel-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:5px;cursor:default}.active-objects-container .panel-header h4{margin:0;padding:5px;background:transparent;font-weight:600;color:#fff;flex:1;font-size:16px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .collapsed-title{color:#fff;font-weight:600;font-size:12px;padding:8px 4px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.active-objects-container .collapsed-title:hover{color:#1976d2}.active-objects-content{display:block;max-height:278px;overflow:auto}.active-objects-content::-webkit-scrollbar{width:12px}.active-objects-content::-webkit-scrollbar-track{background:#757474;border-radius:8px}.active-objects-content::-webkit-scrollbar-thumb{background:#1a1c1f;border-radius:8px;border:2px solid #2a2c30}.active-objects-content::-webkit-scrollbar-thumb:hover{background:#0f1012}.active-objects-content::-webkit-scrollbar-button{width:12px;height:16px;background:#2a2c30;border:1px solid #1a1c1f}.active-objects-content::-webkit-scrollbar-button:vertical:decrement{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 4l-4 4h8z'/%3E%3C/svg%3E\") no-repeat center;border-radius:8px 8px 0 0}.active-objects-content::-webkit-scrollbar-button:vertical:decrement:hover{background-color:#1a1c1f}.active-objects-content::-webkit-scrollbar-button:vertical:increment{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 8l4-4H2z'/%3E%3C/svg%3E\") no-repeat center;border-radius:0 0 8px 8px}.active-objects-content::-webkit-scrollbar-button:vertical:increment:hover{background-color:#1a1c1f}.active-objects-content .zoom-icon{color:#4caf50!important;border-radius:50%;padding:6px;margin:4px;cursor:pointer;transition:all .3s ease;font-size:20px;width:20px;height:20px}.active-objects-content .zoom-icon:hover{background:#4caf5033!important}mat-expansion-panel{border-radius:0!important;box-shadow:none!important}mat-expansion-panel:last-child{border-bottom:none}mat-expansion-panel ::ng-deep .mat-expansion-panel-header{padding:0 16px;font-weight:500}mat-expansion-panel ::ng-deep .mat-expansion-panel-header .mat-content{display:flex;justify-content:space-between;align-items:center;color:#fff}mat-expansion-panel ::ng-deep .mat-expansion-panel-body{padding:0}.item-list{display:flex;flex-direction:column;gap:4px;padding:8px;max-height:300px;overflow-y:auto}.item-list::-webkit-scrollbar{width:6px}.item-list::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.item-list::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.item-list::-webkit-scrollbar-thumb:hover{background:#a8a8a8}@media (max-width: 768px){.active-objects-wrapper{right:.5em;top:8em;max-width:280px;width:280px}.item{font-size:13px;padding:6px 10px}}@media (max-width: 480px){.active-objects-wrapper{right:.5em;left:.5em;max-width:calc(100vw - 1em);width:auto}.item-list{max-height:200px}}\n"] }]
1788
2225
  }], ctorParameters: () => [], propDecorators: { settings: [{
1789
2226
  type: Input,
1790
2227
  args: [{ required: true }]
1791
2228
  }] } });
1792
2229
 
2230
+ class SearchProviderService {
2231
+ _cancelSearch = new Subject();
2232
+ maxSearchResults = 8;
2233
+ searchProviders = [];
2234
+ search(searchString) {
2235
+ this._cancelSearch.next('');
2236
+ let combinedSearch = new Observable();
2237
+ this.searchProviders.forEach(searchProvider => {
2238
+ const search = searchProvider
2239
+ .search(searchString, this.maxSearchResults)
2240
+ .pipe(takeUntil(this._cancelSearch.asObservable()))
2241
+ .pipe(take(this.maxSearchResults));
2242
+ combinedSearch = combinedSearch ? combinedSearch.pipe(mergeWith(search)) : search;
2243
+ });
2244
+ return combinedSearch;
2245
+ }
2246
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SearchProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2247
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SearchProviderService, providedIn: 'root' });
2248
+ }
2249
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SearchProviderService, decorators: [{
2250
+ type: Injectable,
2251
+ args: [{
2252
+ providedIn: 'root'
2253
+ }]
2254
+ }] });
2255
+
2256
+ class WFSSearchService {
2257
+ name = 'WFS Search';
2258
+ _http = inject(HttpClient);
2259
+ wfsFormat = new WFS();
2260
+ wktFormat = new WKT();
2261
+ _searcheableLayers = [];
2262
+ geoJsonFormat = new GeoJSON({ dataProjection: 'EPSG:25832', featureProjection: 'EPSG:25832' });
2263
+ _serializer = new XMLSerializer();
2264
+ search(searchValue, maxCount = 5) {
2265
+ const wftSearches = [];
2266
+ this._searcheableLayers.flatMap(layer => {
2267
+ const filter = like(layer.searchField, `*${searchValue}*`, '*', '?', '/', false);
2268
+ var searchFeature = this.wfsFormat.writeGetFeature({
2269
+ featureTypes: [layer.featureType.includes(':') ? layer.featureType.split(':')[1] : ''],
2270
+ outputFormat: 'application/json',
2271
+ featureNS: '',
2272
+ featurePrefix: '',
2273
+ srsName: 'EPSG:25832',
2274
+ maxFeatures: maxCount,
2275
+ filter
2276
+ });
2277
+ wftSearches.push(this._http.post(layer.baseUrl.replace('wms', 'wfs'), this._serializer.serializeToString(searchFeature), { headers: { 'Content-Type': 'text/xml' }, responseType: 'json' }).pipe(map$1(r => {
2278
+ const result = {
2279
+ title: layer.name,
2280
+ total: r.numberMatched ?? 0,
2281
+ items: r.features.map(f => ({ header: f.properties[layer.headerField], wkt: this._formatWKT(f) }))
2282
+ };
2283
+ return result;
2284
+ })));
2285
+ });
2286
+ return combineLatest(wftSearches);
2287
+ }
2288
+ onSelect(searchResult, targetSrs) {
2289
+ // TO DO : add logic for when an item is selected (right now, the map search component does a highlight on it)
2290
+ }
2291
+ onClear() {
2292
+ // TO DO : add logic for when the results list is cleared
2293
+ }
2294
+ setSearcheableLayers(layers) {
2295
+ console.log('setSearcheableLayers', layers);
2296
+ this._searcheableLayers = layers;
2297
+ }
2298
+ _formatWKT(feature) {
2299
+ const olFeature = this.geoJsonFormat.readFeature(feature);
2300
+ return this.wktFormat.writeFeature(olFeature);
2301
+ }
2302
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: WFSSearchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2303
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: WFSSearchService, providedIn: 'root' });
2304
+ }
2305
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: WFSSearchService, decorators: [{
2306
+ type: Injectable,
2307
+ args: [{
2308
+ providedIn: 'root'
2309
+ }]
2310
+ }] });
2311
+
1793
2312
  class MapSearchComponent {
1794
2313
  searchAddress = '';
1795
- allResults = ['address1', 'address2', 'address3', 'address4'];
2314
+ profile;
2315
+ // allResults = ['address1', 'address2', 'address3', 'address4'];
1796
2316
  filteredResults = [];
1797
2317
  collapsed = true;
1798
2318
  dragPosition = { x: 0, y: 0 };
1799
2319
  POSITION_STORAGE_KEY = 'mapSearchPosition';
2320
+ _mapFilteredLayerGroupsKeyName = 'mapFilteredLayerGroups';
2321
+ _highlight = inject(HighlightService);
2322
+ _searchSubject = new Subject();
2323
+ _searchService = inject(SearchProviderService);
2324
+ _searchProviderService = inject(SearchProviderService);
2325
+ _wfsSearch = inject(WFSSearchService);
2326
+ _layerHelperService = inject(LayerHelperService);
1800
2327
  ngOnInit() {
2328
+ this._layerHelperService.activeLayersChanged
2329
+ .subscribe(() => this._addWFSSearchLayers());
1801
2330
  this.filterResults();
1802
2331
  this._loadPosition();
2332
+ this._addWFSSearch();
2333
+ this._searchSubject.pipe(debounceTime(200), distinctUntilChanged(), switchMap(value => this._searchService.search(value))).subscribe({
2334
+ next: result => {
2335
+ console.log('search results', result);
2336
+ this.filteredResults = result;
2337
+ }
2338
+ });
2339
+ }
2340
+ _addWFSSearch() {
2341
+ this._searchProviderService.searchProviders = [];
2342
+ this._searchProviderService.searchProviders.push(this._wfsSearch);
2343
+ }
2344
+ _addWFSSearchLayers() {
2345
+ if (this.profile) {
2346
+ const cacheValue = localStorage.getItem(`${this._mapFilteredLayerGroupsKeyName}_${this.profile.id}`);
2347
+ if (cacheValue) {
2348
+ const cachedProfileInfo = JSON.parse(cacheValue);
2349
+ const visibleLayerIds = cachedProfileInfo.cachedLayerGroups
2350
+ .flatMap(group => group.layers)
2351
+ .filter(layer => layer.visible)
2352
+ .map(layer => layer.id);
2353
+ const searcheableLayers = cachedProfileInfo.profile
2354
+ .layerGroups.flatMap(group => group.layers)
2355
+ .filter(layer => layer.wfsSearchable && visibleLayerIds.includes(layer.id))
2356
+ .map(layer => ({ featureType: layer.layers, baseUrl: layer.baseUrl, name: layer.name,
2357
+ headerField: layer.headerField, searchField: layer.searchField
2358
+ }));
2359
+ this._wfsSearch.setSearcheableLayers(searcheableLayers);
2360
+ }
2361
+ }
1803
2362
  }
1804
2363
  filterResults() {
1805
2364
  if (!this.searchAddress) {
1806
2365
  this.filteredResults = [];
1807
2366
  return;
1808
2367
  }
1809
- this.filteredResults = this.allResults.filter(r => r.toLowerCase().includes(this.searchAddress.toLowerCase()));
2368
+ this._searchSubject.next(this.searchAddress);
2369
+ // this._wfsSearch.search(this.searchAddress).subscribe(r => {
2370
+ // this.filteredResults = [r];
2371
+ // });
1810
2372
  }
1811
2373
  toggleSearch() {
1812
2374
  this.collapsed = !this.collapsed;
@@ -1815,6 +2377,10 @@ class MapSearchComponent {
1815
2377
  this.filterResults();
1816
2378
  }
1817
2379
  }
2380
+ highlight(wkt, event) {
2381
+ event.stopPropagation();
2382
+ this._highlight.highlight(wkt);
2383
+ }
1818
2384
  onDragEnded(event) {
1819
2385
  const position = event.source.getFreeDragPosition();
1820
2386
  this.dragPosition = position;
@@ -1841,7 +2407,7 @@ class MapSearchComponent {
1841
2407
  }
1842
2408
  }
1843
2409
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MapSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1844
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: MapSearchComponent, isStandalone: true, selector: "lib-map-search", ngImport: i0, template: "<div class=\"search-container\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"search-content\">\n <mat-icon class=\"toggle-icon\" (click)=\"toggleSearch()\">{{ collapsed ? 'search' : 'close' }}</mat-icon>\n @if(!collapsed) {\n <mat-form-field appearance=\"outline\" class=\"search-field\">\n <mat-icon class=\"search-icon\" matPrefix>search</mat-icon>\n <mat-label>S\u00F8ge</mat-label>\n <input\n type=\"text\"\n matInput\n [(ngModel)]=\"searchAddress\"\n [matAutocomplete]=\"auto\"\n (input)=\"filterResults()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let result of filteredResults\" [value]=\"result\">\n {{ result }}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n }\n </div>\n</div>", styles: [".search-container{position:absolute;top:2em;left:25em;z-index:1000;cursor:grab;max-width:400px;min-width:48px;width:auto}.search-container.collapsed{width:48px;min-width:48px;max-width:48px}.search-container.collapsed .search-content{display:flex;justify-content:center;align-items:center;min-width:40px}.search-container.collapsed .toggle-icon{margin:0}.search-container.cdk-drag-dragging{opacity:.8;cursor:grab}.search-content{display:flex;align-items:center;gap:8px;background:color-mix(in srgb,#000 60%,transparent);border-radius:0 0 12px 12px;padding:10px;min-width:40px;transition:all .3s ease;box-sizing:border-box;cursor:default}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:20px;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:6px;flex-shrink:0;margin-right:4px}.toggle-icon:hover{color:#2196f3;background:#2196f314}.drag-handle{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 60%,transparent);padding:4px;cursor:grab;border-radius:8px 8px 0 0}.drag-handle mat-icon{color:#fff;font-size:20px;width:20px;height:20px}.search-field{width:100%;min-width:200px;cursor:pointer;flex:1}.search-field ::ng-deep .mat-mdc-form-field-focus-overlay{background-color:transparent}.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important;border-width:1.5px!important;transition:border-color .3s ease,border-width .3s ease}.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important}.search-field ::ng-deep .mat-mdc-form-field-label{color:#fff!important;font-weight:500;font-size:15px}.search-field ::ng-deep .mat-mdc-form-field.mat-focused .mat-mdc-form-field-label{color:#2196f3!important}.search-field ::ng-deep .mat-mdc-input-element{font-size:15px;color:#fff;font-weight:400;line-height:1.5}.search-field ::ng-deep .mat-mdc-input-element::placeholder{color:#ccc;font-weight:400;opacity:.8}.search-field ::ng-deep .mat-icon.search-icon{color:#fff;margin-left:0;margin-right:8px;transition:color .3s ease}.search-field.mat-focused ::ng-deep .mat-icon.search-icon{color:#2196f3}.search-field ::ng-deep .mdc-floating-label{padding:0 4px;left:40px!important}::ng-deep .mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{margin-left:12px}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{color:#fff!important}::ng-deep .mat-mdc-option .mat-pseudo-checkbox-minimal{color:#fff!important}::ng-deep .mat-mdc-autocomplete-panel{border-radius:12px!important;max-height:320px!important;background:color-mix(in srgb,#000 60%,transparent)!important;box-shadow:0 8px 24px #00000026!important;margin-top:8px!important;overflow:hidden!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:52px!important;margin:4px 8px!important;border-radius:8px!important;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled){background-color:#0000004d!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px;font-weight:400;color:inherit;line-height:1.5}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar{width:6px}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0 12px 12px 0}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px;transition:background .3s ease}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb:hover{background:#a8a8a8}::ng-deep .mat-mdc-text-field-wrapper{background:color-mix(in srgb,#000 60%,transparent);border-radius:8px;box-shadow:#0000004d 0 1px 4px -1px;transition:all .3s cubic-bezier(.4,0,.2,1)}::ng-deep .mat-mdc-text-field-wrapper:hover{box-shadow:0 4px 16px #00000026}::ng-deep .mat-mdc-form-field:not(.mat-form-field-disabled) .mat-mdc-floating-label.mdc-floating-label{color:#fff!important}::ng-deep .mdc-text-field{border-radius:8px!important}@media (max-width: 768px){.search-container{left:2em;top:1.5em;max-width:350px}.search-container.collapsed{width:44px;min-width:44px;max-width:44px}.search-container.collapsed .search-content{padding:6px 3px;min-width:38px}.search-field{min-width:180px}.toggle-icon{font-size:18px;width:18px;height:18px}}@media (max-width: 480px){.search-container{left:1.5em;right:1.5em;max-width:calc(100vw - 3em)}.search-container.collapsed{width:40px;min-width:40px;max-width:40px;right:auto}.search-field{min-width:150px}.search-field ::ng-deep .mat-mdc-input-element{font-size:14px}::ng-deep .mat-mdc-autocomplete-panel{max-height:240px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:48px!important;padding:10px 16px!important}.toggle-icon{font-size:16px;width:16px;height:16px}}::ng-deep .mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{color:#fff!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i5$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i4$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i5$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }] });
2410
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: MapSearchComponent, isStandalone: true, selector: "lib-map-search", inputs: { profile: "profile" }, ngImport: i0, template: "<div class=\"search-container\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle\" cdkDragHandle>\n <mat-icon>search</mat-icon>\n <mat-icon class=\"toggle-icon\" (click)=\"toggleSearch()\">{{ collapsed ? 'flip_to_front' : 'remove' }}</mat-icon>\n </div>\n <div class=\"search-content\" *ngIf=\"!collapsed\">\n <mat-form-field appearance=\"outline\" class=\"search-field\">\n <mat-label>S\u00F8ge</mat-label>\n <input\n type=\"text\"\n matInput\n [(ngModel)]=\"searchAddress\"\n [matAutocomplete]=\"auto\"\n (input)=\"filterResults()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let result of filteredResults\" [value]=\"result\" class=\"search-result-option\">\n {{ result.title }} ({{result.items.length}} af {{ result.total }})\n <div *ngFor=\"let item of result.items\" class=\"search-result-item\">\n {{item.header}} \n <mat-icon (click)=\"highlight(item.wkt, $event)\">highlight</mat-icon>\n </div>\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n </div>\n</div>", styles: [".search-container{position:absolute;top:8em;left:1em;z-index:1000;cursor:grab;max-width:400px;min-width:48px;width:auto}.search-container.collapsed{width:48px;min-width:68px;max-width:48px}.search-container.cdk-drag-dragging{opacity:.8;cursor:grab}.drag-handle{display:flex;align-items:center;justify-content:space-between;background:color-mix(in srgb,#000 60%,transparent);padding:4px;cursor:grab;border-radius:5px 5px 0 0}.drag-handle mat-icon:not(.toggle-icon){color:#fff;font-size:20px;width:20px;height:20px}.search-content{display:flex;align-items:center;background:color-mix(in srgb,#000 60%,transparent);padding:5px;transition:all .3s ease;box-sizing:border-box;cursor:default;border-radius:0 0 5px 5px}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:18px!important;width:18px!important;height:18px!important;display:flex;align-items:center;justify-content:center;border-radius:4px;padding:2px;flex-shrink:0}.toggle-icon:hover{color:#fff;background:#ffffff26}.search-field{width:100%;min-width:200px;cursor:pointer;flex:1}.search-field ::ng-deep .mat-mdc-form-field-focus-overlay{background-color:transparent}.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important;border-width:1.5px!important;transition:border-color .3s ease,border-width .3s ease}.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important}.search-field ::ng-deep .mat-mdc-form-field-label{color:#fff!important;font-weight:500;font-size:15px}.search-field ::ng-deep .mat-mdc-form-field.mat-focused .mat-mdc-form-field-label{color:#2196f3!important}.search-field ::ng-deep .mat-mdc-input-element{font-size:15px;color:#fff;font-weight:400;line-height:1.5}.search-field ::ng-deep .mat-mdc-input-element::placeholder{color:#ccc;font-weight:400;opacity:.8}.search-field ::ng-deep .mdc-floating-label{padding:0 4px;left:40px!important}::ng-deep .mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{margin-left:12px;color:#fff!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{color:#fff!important}::ng-deep .mat-mdc-option .mat-pseudo-checkbox-minimal{color:#fff!important}::ng-deep .mat-mdc-form-field-flex{height:40px!important}::ng-deep .mat-mdc-autocomplete-panel{border-radius:12px!important;max-height:320px!important;background:color-mix(in srgb,#000 85%,transparent)!important;box-shadow:0 8px 24px #00000026!important;margin-top:8px!important;overflow:hidden!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:30px!important;border-radius:8px!important;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;overflow:auto}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled){background-color:#0000004d!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px;font-weight:400;color:inherit;line-height:1.5}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar{width:6px}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0 12px 12px 0}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px;transition:background .3s ease}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb:hover{background:#a8a8a8}::ng-deep .mat-mdc-text-field-wrapper{background:color-mix(in srgb,#000 60%,transparent);border-radius:8px;box-shadow:#0000004d 0 1px 4px -1px;transition:all .3s cubic-bezier(.4,0,.2,1)}::ng-deep .mat-mdc-text-field-wrapper:hover{box-shadow:0 4px 16px #00000026}::ng-deep .mat-mdc-form-field:not(.mat-form-field-disabled) .mat-mdc-floating-label.mdc-floating-label{color:#fff!important}::ng-deep .mdc-text-field{border-radius:8px!important}@media (max-width: 768px){.search-container{left:2em;top:1.5em;max-width:350px}.search-container.collapsed{width:44px;min-width:44px;max-width:44px}.search-field{min-width:180px}.toggle-icon{font-size:18px;width:18px;height:18px}}@media (max-width: 480px){.search-container{left:1.5em;right:1.5em;max-width:calc(100vw - 3em)}.search-container.collapsed{width:40px;min-width:40px;max-width:40px;right:auto}.search-field{min-width:150px}.search-field ::ng-deep .mat-mdc-input-element{font-size:14px}::ng-deep .mat-mdc-autocomplete-panel{max-height:240px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:48px!important;padding:10px 16px!important}.toggle-icon{font-size:16px;width:16px;height:16px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i5$2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i4$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i5$2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }] });
1845
2411
  }
1846
2412
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MapSearchComponent, decorators: [{
1847
2413
  type: Component,
@@ -1854,8 +2420,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1854
2420
  MatOptionModule,
1855
2421
  MatIconModule,
1856
2422
  DragDropModule
1857
- ], template: "<div class=\"search-container\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"search-content\">\n <mat-icon class=\"toggle-icon\" (click)=\"toggleSearch()\">{{ collapsed ? 'search' : 'close' }}</mat-icon>\n @if(!collapsed) {\n <mat-form-field appearance=\"outline\" class=\"search-field\">\n <mat-icon class=\"search-icon\" matPrefix>search</mat-icon>\n <mat-label>S\u00F8ge</mat-label>\n <input\n type=\"text\"\n matInput\n [(ngModel)]=\"searchAddress\"\n [matAutocomplete]=\"auto\"\n (input)=\"filterResults()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let result of filteredResults\" [value]=\"result\">\n {{ result }}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n }\n </div>\n</div>", styles: [".search-container{position:absolute;top:2em;left:25em;z-index:1000;cursor:grab;max-width:400px;min-width:48px;width:auto}.search-container.collapsed{width:48px;min-width:48px;max-width:48px}.search-container.collapsed .search-content{display:flex;justify-content:center;align-items:center;min-width:40px}.search-container.collapsed .toggle-icon{margin:0}.search-container.cdk-drag-dragging{opacity:.8;cursor:grab}.search-content{display:flex;align-items:center;gap:8px;background:color-mix(in srgb,#000 60%,transparent);border-radius:0 0 12px 12px;padding:10px;min-width:40px;transition:all .3s ease;box-sizing:border-box;cursor:default}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:20px;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:6px;flex-shrink:0;margin-right:4px}.toggle-icon:hover{color:#2196f3;background:#2196f314}.drag-handle{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 60%,transparent);padding:4px;cursor:grab;border-radius:8px 8px 0 0}.drag-handle mat-icon{color:#fff;font-size:20px;width:20px;height:20px}.search-field{width:100%;min-width:200px;cursor:pointer;flex:1}.search-field ::ng-deep .mat-mdc-form-field-focus-overlay{background-color:transparent}.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important;border-width:1.5px!important;transition:border-color .3s ease,border-width .3s ease}.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important}.search-field ::ng-deep .mat-mdc-form-field-label{color:#fff!important;font-weight:500;font-size:15px}.search-field ::ng-deep .mat-mdc-form-field.mat-focused .mat-mdc-form-field-label{color:#2196f3!important}.search-field ::ng-deep .mat-mdc-input-element{font-size:15px;color:#fff;font-weight:400;line-height:1.5}.search-field ::ng-deep .mat-mdc-input-element::placeholder{color:#ccc;font-weight:400;opacity:.8}.search-field ::ng-deep .mat-icon.search-icon{color:#fff;margin-left:0;margin-right:8px;transition:color .3s ease}.search-field.mat-focused ::ng-deep .mat-icon.search-icon{color:#2196f3}.search-field ::ng-deep .mdc-floating-label{padding:0 4px;left:40px!important}::ng-deep .mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{margin-left:12px}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{color:#fff!important}::ng-deep .mat-mdc-option .mat-pseudo-checkbox-minimal{color:#fff!important}::ng-deep .mat-mdc-autocomplete-panel{border-radius:12px!important;max-height:320px!important;background:color-mix(in srgb,#000 60%,transparent)!important;box-shadow:0 8px 24px #00000026!important;margin-top:8px!important;overflow:hidden!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:52px!important;margin:4px 8px!important;border-radius:8px!important;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled){background-color:#0000004d!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px;font-weight:400;color:inherit;line-height:1.5}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar{width:6px}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0 12px 12px 0}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px;transition:background .3s ease}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb:hover{background:#a8a8a8}::ng-deep .mat-mdc-text-field-wrapper{background:color-mix(in srgb,#000 60%,transparent);border-radius:8px;box-shadow:#0000004d 0 1px 4px -1px;transition:all .3s cubic-bezier(.4,0,.2,1)}::ng-deep .mat-mdc-text-field-wrapper:hover{box-shadow:0 4px 16px #00000026}::ng-deep .mat-mdc-form-field:not(.mat-form-field-disabled) .mat-mdc-floating-label.mdc-floating-label{color:#fff!important}::ng-deep .mdc-text-field{border-radius:8px!important}@media (max-width: 768px){.search-container{left:2em;top:1.5em;max-width:350px}.search-container.collapsed{width:44px;min-width:44px;max-width:44px}.search-container.collapsed .search-content{padding:6px 3px;min-width:38px}.search-field{min-width:180px}.toggle-icon{font-size:18px;width:18px;height:18px}}@media (max-width: 480px){.search-container{left:1.5em;right:1.5em;max-width:calc(100vw - 3em)}.search-container.collapsed{width:40px;min-width:40px;max-width:40px;right:auto}.search-field{min-width:150px}.search-field ::ng-deep .mat-mdc-input-element{font-size:14px}::ng-deep .mat-mdc-autocomplete-panel{max-height:240px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:48px!important;padding:10px 16px!important}.toggle-icon{font-size:16px;width:16px;height:16px}}::ng-deep .mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{color:#fff!important}\n"] }]
1858
- }] });
2423
+ ], template: "<div class=\"search-container\" \n cdkDrag \n cdkDragBoundary=\".map-container\" \n [cdkDragFreeDragPosition]=\"dragPosition\"\n (cdkDragEnded)=\"onDragEnded($event)\"\n [class.collapsed]=\"collapsed\">\n <div class=\"drag-handle\" cdkDragHandle>\n <mat-icon>search</mat-icon>\n <mat-icon class=\"toggle-icon\" (click)=\"toggleSearch()\">{{ collapsed ? 'flip_to_front' : 'remove' }}</mat-icon>\n </div>\n <div class=\"search-content\" *ngIf=\"!collapsed\">\n <mat-form-field appearance=\"outline\" class=\"search-field\">\n <mat-label>S\u00F8ge</mat-label>\n <input\n type=\"text\"\n matInput\n [(ngModel)]=\"searchAddress\"\n [matAutocomplete]=\"auto\"\n (input)=\"filterResults()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let result of filteredResults\" [value]=\"result\" class=\"search-result-option\">\n {{ result.title }} ({{result.items.length}} af {{ result.total }})\n <div *ngFor=\"let item of result.items\" class=\"search-result-item\">\n {{item.header}} \n <mat-icon (click)=\"highlight(item.wkt, $event)\">highlight</mat-icon>\n </div>\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n </div>\n</div>", styles: [".search-container{position:absolute;top:8em;left:1em;z-index:1000;cursor:grab;max-width:400px;min-width:48px;width:auto}.search-container.collapsed{width:48px;min-width:68px;max-width:48px}.search-container.cdk-drag-dragging{opacity:.8;cursor:grab}.drag-handle{display:flex;align-items:center;justify-content:space-between;background:color-mix(in srgb,#000 60%,transparent);padding:4px;cursor:grab;border-radius:5px 5px 0 0}.drag-handle mat-icon:not(.toggle-icon){color:#fff;font-size:20px;width:20px;height:20px}.search-content{display:flex;align-items:center;background:color-mix(in srgb,#000 60%,transparent);padding:5px;transition:all .3s ease;box-sizing:border-box;cursor:default;border-radius:0 0 5px 5px}.toggle-icon{cursor:pointer;color:#fff;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:18px!important;width:18px!important;height:18px!important;display:flex;align-items:center;justify-content:center;border-radius:4px;padding:2px;flex-shrink:0}.toggle-icon:hover{color:#fff;background:#ffffff26}.search-field{width:100%;min-width:200px;cursor:pointer;flex:1}.search-field ::ng-deep .mat-mdc-form-field-focus-overlay{background-color:transparent}.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important;border-width:1.5px!important;transition:border-color .3s ease,border-width .3s ease}.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__leading,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__notch,.search-field:not(.mat-focused):hover ::ng-deep .mdc-notched-outline .mdc-notched-outline__trailing{border-color:transparent!important}.search-field ::ng-deep .mat-mdc-form-field-label{color:#fff!important;font-weight:500;font-size:15px}.search-field ::ng-deep .mat-mdc-form-field.mat-focused .mat-mdc-form-field-label{color:#2196f3!important}.search-field ::ng-deep .mat-mdc-input-element{font-size:15px;color:#fff;font-weight:400;line-height:1.5}.search-field ::ng-deep .mat-mdc-input-element::placeholder{color:#ccc;font-weight:400;opacity:.8}.search-field ::ng-deep .mdc-floating-label{padding:0 4px;left:40px!important}::ng-deep .mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{margin-left:12px;color:#fff!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{color:#fff!important}::ng-deep .mat-mdc-option .mat-pseudo-checkbox-minimal{color:#fff!important}::ng-deep .mat-mdc-form-field-flex{height:40px!important}::ng-deep .mat-mdc-autocomplete-panel{border-radius:12px!important;max-height:320px!important;background:color-mix(in srgb,#000 85%,transparent)!important;box-shadow:0 8px 24px #00000026!important;margin-top:8px!important;overflow:hidden!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:30px!important;border-radius:8px!important;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;overflow:auto}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled){background-color:#0000004d!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item__primary-text{font-size:14px;font-weight:400;color:inherit;line-height:1.5}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar{width:6px}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0 12px 12px 0}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px;transition:background .3s ease}::ng-deep .mat-mdc-autocomplete-panel::-webkit-scrollbar-thumb:hover{background:#a8a8a8}::ng-deep .mat-mdc-text-field-wrapper{background:color-mix(in srgb,#000 60%,transparent);border-radius:8px;box-shadow:#0000004d 0 1px 4px -1px;transition:all .3s cubic-bezier(.4,0,.2,1)}::ng-deep .mat-mdc-text-field-wrapper:hover{box-shadow:0 4px 16px #00000026}::ng-deep .mat-mdc-form-field:not(.mat-form-field-disabled) .mat-mdc-floating-label.mdc-floating-label{color:#fff!important}::ng-deep .mdc-text-field{border-radius:8px!important}@media (max-width: 768px){.search-container{left:2em;top:1.5em;max-width:350px}.search-container.collapsed{width:44px;min-width:44px;max-width:44px}.search-field{min-width:180px}.toggle-icon{font-size:18px;width:18px;height:18px}}@media (max-width: 480px){.search-container{left:1.5em;right:1.5em;max-width:calc(100vw - 3em)}.search-container.collapsed{width:40px;min-width:40px;max-width:40px;right:auto}.search-field{min-width:150px}.search-field ::ng-deep .mat-mdc-input-element{font-size:14px}::ng-deep .mat-mdc-autocomplete-panel{max-height:240px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{min-height:48px!important;padding:10px 16px!important}.toggle-icon{font-size:16px;width:16px;height:16px}}\n"] }]
2424
+ }], propDecorators: { profile: [{
2425
+ type: Input
2426
+ }] } });
1859
2427
 
1860
2428
  class LayerService {
1861
2429
  config = inject(GISKOMPONENT_CONFIG);
@@ -1875,13 +2443,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1875
2443
  }] });
1876
2444
 
1877
2445
  class LegendsListComponent {
2446
+ _http = inject(HttpClient);
1878
2447
  ngOnInit() {
1879
2448
  this._initializeMapIconControl();
1880
- this._layerHelperService.activeLayersChanged.subscribe(() => this._setFilteredLegends());
2449
+ this._layerHelperService.activeLayersChanged.subscribe(() => this._setFilteredLegends().subscribe(result => this.filteredLayersDetailed = result));
1881
2450
  }
1882
2451
  ngOnChanges(changes) {
1883
2452
  if (changes['profile'] && this.profile)
1884
- this._setFilteredLegends();
2453
+ this._setFilteredLegends().subscribe(result => this.filteredLayersDetailed = result);
1885
2454
  }
1886
2455
  set contentIcon(content) {
1887
2456
  this._legendsListIcon = content;
@@ -1900,7 +2469,7 @@ class LegendsListComponent {
1900
2469
  _legendsListIconControl;
1901
2470
  _legendsListBody;
1902
2471
  _legendsListBodyControl;
1903
- _layerIdsToDisplayInMapKeyName = 'layerIdsToDisplayInMap';
2472
+ _mapFilteredLayerGroupsKeyName = 'mapFilteredLayerGroups';
1904
2473
  _layerService = inject(LayerService);
1905
2474
  _layerHelperService = inject(LayerHelperService);
1906
2475
  toggleLegendsList() {
@@ -1933,23 +2502,60 @@ class LegendsListComponent {
1933
2502
  this.map.removeControl(this._legendsListBodyControl);
1934
2503
  }
1935
2504
  _setFilteredLegends() {
1936
- if (this.profile?.id) {
1937
- const layerIdsCachedToDisplay = localStorage.getItem(`${this._layerIdsToDisplayInMapKeyName}_${this.profile?.id}`)?.split(',').map(Number);
1938
- if (layerIdsCachedToDisplay) {
1939
- this._layerService.getByIds(layerIdsCachedToDisplay)
1940
- .subscribe(layers => {
1941
- this.filteredLayersDetailed = layers.map(l => ({ ...l, imageUrl: l.legend?.imageName ? this._getImageUrl(l.legend.imageName) : l.legend?.imageExternalURL ?? '' }));
1942
- });
1943
- }
2505
+ if (!this.profile?.id) {
2506
+ return of([]);
2507
+ }
2508
+ const cacheValue = localStorage.getItem(`${this._mapFilteredLayerGroupsKeyName}_${this.profile?.id}`);
2509
+ if (!cacheValue) {
2510
+ return of([]);
2511
+ }
2512
+ const layerIdsCachedToDisplay = JSON.parse(cacheValue).cachedLayerGroups
2513
+ .flatMap((lg) => lg.layers)
2514
+ .filter((l) => l.visible)
2515
+ .map((l) => l.id);
2516
+ if (!layerIdsCachedToDisplay) {
2517
+ return of([]);
2518
+ }
2519
+ return this._layerService.getByIds(layerIdsCachedToDisplay)
2520
+ .pipe(switchMap(layers => {
2521
+ const enriched$ = layers.map(layer => this.resolveLegendImage(layer));
2522
+ return forkJoin(enriched$); // Wait until all items are enriched
2523
+ }));
2524
+ }
2525
+ resolveLegendImage(layer) {
2526
+ if (layer.legend?.imageName) {
2527
+ return of({
2528
+ ...layer,
2529
+ imageUrl: this._getImageUrl(layer.legend.imageName)
2530
+ });
1944
2531
  }
2532
+ if (layer.legend?.imageExternalURL) {
2533
+ return of({
2534
+ ...layer,
2535
+ imageUrl: layer.legend.imageExternalURL
2536
+ });
2537
+ }
2538
+ // Fallback to Geoserver legend file
2539
+ const fallbackUrl = `${layer.baseUrl}?service=WMS&REQUEST=GetLegendGraphic&VERSION=1.0.0&FORMAT=image/png&WIDTH=20&HEIGHT=20&STRICT=false&layer=${layer.layers}`;
2540
+ return this._http.get(fallbackUrl, { responseType: 'blob' }).pipe(map(blob => {
2541
+ // Blob returned as an image, so layer has a legend in Geoserver
2542
+ const isImage = blob.type.startsWith('image/');
2543
+ return {
2544
+ ...layer,
2545
+ imageUrl: isImage ? fallbackUrl : ''
2546
+ };
2547
+ }), catchError(() => of({
2548
+ ...layer,
2549
+ imageUrl: '' // fallback failed, layer has no legend on Geoserver
2550
+ })));
1945
2551
  }
1946
2552
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LegendsListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1947
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: LegendsListComponent, isStandalone: true, selector: "lib-legends-list", inputs: { map: "map", profile: "profile" }, viewQueries: [{ propertyName: "contentIcon", first: true, predicate: ["legendsListIcon"], descendants: true }, { propertyName: "contentBody", first: true, predicate: ["legendsListBody"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #legendsListIcon class=\"ol-unselectable ol-control legends-list-icon\">\n <mat-icon (click)=\"toggleLegendsList()\">area_chart</mat-icon>\n</div>\n<div #legendsListBody [class.display-none]=\"!showList\" class=\"legends-list-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"ol-unselectable ol-control legends-list-body\">\n <div class=\"item-list\">\n @for (layer of filteredLayersDetailed; track layer.id; let iIndex = $index) {\n @if (layer.imageUrl) {\n <mat-expansion-panel expanded=\"true\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" ><span>{{ layer.name }}</span></div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n <div class=\"legend\">\n <span><img [src]=\"layer.imageUrl\" class=\"legend-thumbnail\"/></span>\n </div>\n </mat-expansion-panel>\n }\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .legends-list-icon{position:absolute;left:auto;right:8em;bottom:.5em;z-index:1000}::ng-deep .legends-list-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .legends-list-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.legends-list-body-wrapper{position:absolute;left:auto;right:36em;bottom:4em;z-index:1000;cursor:grab}.legends-list-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.legends-list-body-wrapper .ol-control{border-radius:0}.drag-handle-selector{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 40%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab;box-shadow:0 -2px 8px #0003}.drag-handle-selector mat-icon{color:#fff;font-size:20px;width:20px;height:20px}::ng-deep .legends-list-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 40%,transparent);box-shadow:0 4px 20px #00000026;width:290px;max-height:500px;overflow:hidden;display:flex;flex-direction:column}::ng-deep .legends-list-body .item-list{flex:1;overflow-y:auto;padding:6px;max-height:900px}::ng-deep .legends-list-body .item-list .legend{margin-bottom:6px;overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .legends-list-body .item-list .legend span{color:#fff}::ng-deep .legends-list-body .item-list .item{display:flex;align-items:center;gap:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}::ng-deep .legends-list-body .item-list .item:last-child{border-bottom:none}.display-none{display:none}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar{width:8px;border-radius:10px;border:5px solid transparent}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb{background:#0000004d;border:5px solid transparent;border-radius:10px;background-clip:padding-box}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb:hover{background:#0006;background-clip:padding-box;border:3px solid transparent}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatInputModule }] });
2553
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: LegendsListComponent, isStandalone: true, selector: "lib-legends-list", inputs: { map: "map", profile: "profile" }, viewQueries: [{ propertyName: "contentIcon", first: true, predicate: ["legendsListIcon"], descendants: true }, { propertyName: "contentBody", first: true, predicate: ["legendsListBody"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #legendsListIcon class=\"ol-unselectable ol-control legends-list-icon\">\n <mat-icon (click)=\"toggleLegendsList()\">area_chart</mat-icon>\n</div>\n<div #legendsListBody [class.display-none]=\"!showList\" class=\"legends-list-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <div class=\"drag-handle-content\">\n <div class=\"drag-handle-icons\">\n <mat-icon class=\"drag-indicator-right\">open_with</mat-icon>\n <mat-icon class=\"minimize-button\" (click)=\"toggleLegendsList()\">minimize</mat-icon>\n </div>\n </div>\n </div>\n <div class=\"ol-unselectable ol-control legends-list-body\">\n <div class=\"item-list\">\n @for (layer of filteredLayersDetailed; track layer.id; let iIndex = $index) {\n @if (layer.imageUrl) {\n <mat-expansion-panel expanded=\"true\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" ><span>{{ layer.name }}</span></div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n <div class=\"legend\">\n <span><img [src]=\"layer.imageUrl\" class=\"legend-thumbnail\"/></span>\n </div>\n </mat-expansion-panel>\n }\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .legends-list-icon{position:absolute;left:auto;right:1em;bottom:1em;z-index:1000}::ng-deep .legends-list-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .legends-list-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.display-none{display:none!important}::ng-deep .legends-list-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 60%,transparent);box-shadow:0 4px 20px #00000026;width:250px;max-height:700px;min-height:80px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 1024px){::ng-deep .legends-list-body{width:240px;max-height:550px;min-height:70px}}@media (max-width: 768px){::ng-deep .legends-list-body{width:100%;max-height:60vh;max-height:calc(var(--vh, 1vh) * 60);min-height:100px}}@media (max-width: 480px){::ng-deep .legends-list-body{max-height:70vh;max-height:calc(var(--vh, 1vh) * 70);min-height:90px}}.legends-list-body-wrapper{position:absolute;left:auto;right:35em;bottom:.2em;z-index:1000;cursor:grab;width:fit-content;max-width:250px}@media (max-width: 1024px){.legends-list-body-wrapper{right:32em;bottom:.5em;max-width:240px}}@media (max-width: 768px){.legends-list-body-wrapper{position:fixed;right:3em;left:1em;bottom:5em;width:calc(100% - 7em);max-width:100%}}@media (max-width: 480px){.legends-list-body-wrapper{bottom:4em}}.legends-list-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grabbing;z-index:1001}.legends-list-body-wrapper .ol-control{border-radius:0}.drag-handle-selector{display:flex;align-items:center;justify-content:flex-end;border-radius:5px 5px 0 0;padding:5px;cursor:grab;background:#000}.drag-handle-content{display:flex;align-items:center;justify-content:flex-end;width:100%}.drag-handle-icons{display:flex;align-items:center;gap:16px}.drag-indicator-right{color:#fff;font-size:18px;width:18px;height:18px;cursor:grab;transition:all .2s ease}.minimize-button{color:#fff;font-size:18px;width:18px;height:18px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;transform:translateY(-30%)}.minimize-button:hover{color:#fff;background:#ffffff26}.drag-handle-selector{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 60%,transparent);border-radius:5px 5px 0 0;padding:5px;cursor:grab;box-shadow:0 -2px 8px #0003;position:sticky;top:0;z-index:1}@media (max-width: 768px){.drag-handle-selector{padding:8px}}.drag-handle-selector mat-icon{color:#fff;font-size:18px;width:18px;height:18px}@media (max-width: 768px){.drag-handle-selector mat-icon{font-size:20px;width:20px;height:20px}}::ng-deep .legends-list-body .item-list{flex:1 1 auto;overflow-y:auto;padding:4px;min-height:0;background:#000}@media (max-width: 768px){::ng-deep .legends-list-body .item-list{padding:6px}}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header{padding:0 8px;height:40px!important;min-height:40px!important}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header .mat-content{display:flex;align-items:center}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header .mat-expansion-panel-header-title{font-weight:600;color:#fff;font-size:17px}::ng-deep .legends-list-body .item-list .mat-expansion-panel-body{padding:4px 8px 0!important}::ng-deep .legends-list-body .item-list .legend{overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .legends-list-body .item-list .legend span{color:#fff}::ng-deep .legends-list-body .item-list .item{display:flex;align-items:center;gap:4px;padding:6px 0;background:transparent;transition:all .2s ease;color:#bdc1c3cc;cursor:grab;min-width:0;flex:1}::ng-deep .legends-list-body .item-list .item span{word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;white-space:normal;flex:1;min-width:0}@media (max-width: 768px){::ng-deep .legends-list-body .item-list .item{padding:8px 12px;gap:6px}}@media (max-width: 768px){::ng-deep .legends-list-body .item-list mat-expansion-panel{margin-bottom:6px}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header{padding:0 6px;height:18px!important;min-height:18px!important}::ng-deep .legends-list-body .item-list .legend{padding:6px}::ng-deep .legends-list-body .item-list .legend-thumbnail{max-width:100%;height:auto;max-height:120px}}.legend-thumbnail{max-width:150px;max-height:150px;width:auto;height:auto;border:1px solid #dee2e6;border-radius:4px;padding:4px}@media (max-width: 768px){.legend-thumbnail{max-width:100%;max-height:120px;padding:3px}}::ng-deep .legends-list-body .item-list::-webkit-scrollbar{width:12px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-track{background:#757474;border-radius:8px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb{background:#1a1c1f;border-radius:8px;border:2px solid #2a2c30}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb:hover{background:#0f1012}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button{width:12px;height:16px;background:#2a2c30;border:1px solid #1a1c1f}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:decrement{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 4l-4 4h8z'/%3E%3C/svg%3E\") no-repeat center;border-radius:8px 8px 0 0}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:decrement:hover{background-color:#1a1c1f}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:increment{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 8l4-4H2z'/%3E%3C/svg%3E\") no-repeat center;border-radius:0 0 8px 8px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:increment:hover{background-color:#1a1c1f}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatInputModule }] });
1948
2554
  }
1949
2555
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LegendsListComponent, decorators: [{
1950
2556
  type: Component,
1951
2557
  args: [{ selector: 'lib-legends-list', imports: [MatFormFieldModule, CommonModule, MatIconModule, FormsModule, DragDropModule,
1952
- MatExpansionModule, MatInputModule], template: "<div #legendsListIcon class=\"ol-unselectable ol-control legends-list-icon\">\n <mat-icon (click)=\"toggleLegendsList()\">area_chart</mat-icon>\n</div>\n<div #legendsListBody [class.display-none]=\"!showList\" class=\"legends-list-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <mat-icon>drag_indicator</mat-icon>\n </div>\n <div class=\"ol-unselectable ol-control legends-list-body\">\n <div class=\"item-list\">\n @for (layer of filteredLayersDetailed; track layer.id; let iIndex = $index) {\n @if (layer.imageUrl) {\n <mat-expansion-panel expanded=\"true\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" ><span>{{ layer.name }}</span></div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n <div class=\"legend\">\n <span><img [src]=\"layer.imageUrl\" class=\"legend-thumbnail\"/></span>\n </div>\n </mat-expansion-panel>\n }\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .legends-list-icon{position:absolute;left:auto;right:8em;bottom:.5em;z-index:1000}::ng-deep .legends-list-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .legends-list-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.legends-list-body-wrapper{position:absolute;left:auto;right:36em;bottom:4em;z-index:1000;cursor:grab}.legends-list-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grab;z-index:1001}.legends-list-body-wrapper .ol-control{border-radius:0}.drag-handle-selector{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 40%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab;box-shadow:0 -2px 8px #0003}.drag-handle-selector mat-icon{color:#fff;font-size:20px;width:20px;height:20px}::ng-deep .legends-list-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 40%,transparent);box-shadow:0 4px 20px #00000026;width:290px;max-height:500px;overflow:hidden;display:flex;flex-direction:column}::ng-deep .legends-list-body .item-list{flex:1;overflow-y:auto;padding:6px;max-height:900px}::ng-deep .legends-list-body .item-list .legend{margin-bottom:6px;overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .legends-list-body .item-list .legend span{color:#fff}::ng-deep .legends-list-body .item-list .item{display:flex;align-items:center;gap:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}::ng-deep .legends-list-body .item-list .item:last-child{border-bottom:none}.display-none{display:none}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar{width:8px;border-radius:10px;border:5px solid transparent}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb{background:#0000004d;border:5px solid transparent;border-radius:10px;background-clip:padding-box}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb:hover{background:#0006;background-clip:padding-box;border:3px solid transparent}\n"] }]
2558
+ MatExpansionModule, MatInputModule], template: "<div #legendsListIcon class=\"ol-unselectable ol-control legends-list-icon\">\n <mat-icon (click)=\"toggleLegendsList()\">area_chart</mat-icon>\n</div>\n<div #legendsListBody [class.display-none]=\"!showList\" class=\"legends-list-body-wrapper\" cdkDrag cdkDragBoundary=\".map-container\">\n <div class=\"drag-handle-selector\" cdkDragHandle>\n <div class=\"drag-handle-content\">\n <div class=\"drag-handle-icons\">\n <mat-icon class=\"drag-indicator-right\">open_with</mat-icon>\n <mat-icon class=\"minimize-button\" (click)=\"toggleLegendsList()\">minimize</mat-icon>\n </div>\n </div>\n </div>\n <div class=\"ol-unselectable ol-control legends-list-body\">\n <div class=\"item-list\">\n @for (layer of filteredLayersDetailed; track layer.id; let iIndex = $index) {\n @if (layer.imageUrl) {\n <mat-expansion-panel expanded=\"true\"> \n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"item\" ><span>{{ layer.name }}</span></div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n <div class=\"legend\">\n <span><img [src]=\"layer.imageUrl\" class=\"legend-thumbnail\"/></span>\n </div>\n </mat-expansion-panel>\n }\n }\n </div>\n </div>\n</div>", styles: ["::ng-deep .legends-list-icon{position:absolute;left:auto;right:1em;bottom:1em;z-index:1000}::ng-deep .legends-list-icon mat-icon{display:flex;justify-content:center;align-items:center;cursor:pointer;transition:all .3s ease;outline:none;border:0;height:40px;border-radius:5px;width:40px;background:color-mix(in srgb,#000 60%,transparent);box-shadow:#0000004d 0 1px 4px -1px;font-size:2em;color:#fff}::ng-deep .legends-list-icon mat-icon:hover{box-shadow:0 4px 12px #0003;color:#fff}.display-none{display:none!important}::ng-deep .legends-list-body{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;background:color-mix(in srgb,#000 60%,transparent);box-shadow:0 4px 20px #00000026;width:250px;max-height:700px;min-height:80px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 1024px){::ng-deep .legends-list-body{width:240px;max-height:550px;min-height:70px}}@media (max-width: 768px){::ng-deep .legends-list-body{width:100%;max-height:60vh;max-height:calc(var(--vh, 1vh) * 60);min-height:100px}}@media (max-width: 480px){::ng-deep .legends-list-body{max-height:70vh;max-height:calc(var(--vh, 1vh) * 70);min-height:90px}}.legends-list-body-wrapper{position:absolute;left:auto;right:35em;bottom:.2em;z-index:1000;cursor:grab;width:fit-content;max-width:250px}@media (max-width: 1024px){.legends-list-body-wrapper{right:32em;bottom:.5em;max-width:240px}}@media (max-width: 768px){.legends-list-body-wrapper{position:fixed;right:3em;left:1em;bottom:5em;width:calc(100% - 7em);max-width:100%}}@media (max-width: 480px){.legends-list-body-wrapper{bottom:4em}}.legends-list-body-wrapper.cdk-drag-dragging{opacity:.8;cursor:grabbing;z-index:1001}.legends-list-body-wrapper .ol-control{border-radius:0}.drag-handle-selector{display:flex;align-items:center;justify-content:flex-end;border-radius:5px 5px 0 0;padding:5px;cursor:grab;background:#000}.drag-handle-content{display:flex;align-items:center;justify-content:flex-end;width:100%}.drag-handle-icons{display:flex;align-items:center;gap:16px}.drag-indicator-right{color:#fff;font-size:18px;width:18px;height:18px;cursor:grab;transition:all .2s ease}.minimize-button{color:#fff;font-size:18px;width:18px;height:18px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;transform:translateY(-30%)}.minimize-button:hover{color:#fff;background:#ffffff26}.drag-handle-selector{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,#000 60%,transparent);border-radius:5px 5px 0 0;padding:5px;cursor:grab;box-shadow:0 -2px 8px #0003;position:sticky;top:0;z-index:1}@media (max-width: 768px){.drag-handle-selector{padding:8px}}.drag-handle-selector mat-icon{color:#fff;font-size:18px;width:18px;height:18px}@media (max-width: 768px){.drag-handle-selector mat-icon{font-size:20px;width:20px;height:20px}}::ng-deep .legends-list-body .item-list{flex:1 1 auto;overflow-y:auto;padding:4px;min-height:0;background:#000}@media (max-width: 768px){::ng-deep .legends-list-body .item-list{padding:6px}}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header{padding:0 8px;height:40px!important;min-height:40px!important}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header .mat-content{display:flex;align-items:center}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header .mat-expansion-panel-header-title{font-weight:600;color:#fff;font-size:17px}::ng-deep .legends-list-body .item-list .mat-expansion-panel-body{padding:4px 8px 0!important}::ng-deep .legends-list-body .item-list .legend{overflow:hidden;box-shadow:0 -2px 2px #4868b20a,0 2px 2px #6a6f7517,0 1px 2px #4868b214}::ng-deep .legends-list-body .item-list .legend span{color:#fff}::ng-deep .legends-list-body .item-list .item{display:flex;align-items:center;gap:4px;padding:6px 0;background:transparent;transition:all .2s ease;color:#bdc1c3cc;cursor:grab;min-width:0;flex:1}::ng-deep .legends-list-body .item-list .item span{word-wrap:break-word;word-break:break-word;overflow-wrap:break-word;white-space:normal;flex:1;min-width:0}@media (max-width: 768px){::ng-deep .legends-list-body .item-list .item{padding:8px 12px;gap:6px}}@media (max-width: 768px){::ng-deep .legends-list-body .item-list mat-expansion-panel{margin-bottom:6px}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header{padding:0 6px;height:18px!important;min-height:18px!important}::ng-deep .legends-list-body .item-list .legend{padding:6px}::ng-deep .legends-list-body .item-list .legend-thumbnail{max-width:100%;height:auto;max-height:120px}}.legend-thumbnail{max-width:150px;max-height:150px;width:auto;height:auto;border:1px solid #dee2e6;border-radius:4px;padding:4px}@media (max-width: 768px){.legend-thumbnail{max-width:100%;max-height:120px;padding:3px}}::ng-deep .legends-list-body .item-list::-webkit-scrollbar{width:12px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-track{background:#757474;border-radius:8px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb{background:#1a1c1f;border-radius:8px;border:2px solid #2a2c30}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-thumb:hover{background:#0f1012}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button{width:12px;height:16px;background:#2a2c30;border:1px solid #1a1c1f}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:decrement{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 4l-4 4h8z'/%3E%3C/svg%3E\") no-repeat center;border-radius:8px 8px 0 0}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:decrement:hover{background-color:#1a1c1f}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:increment{background:#2a2c30 url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 8l4-4H2z'/%3E%3C/svg%3E\") no-repeat center;border-radius:0 0 8px 8px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar-button:vertical:increment:hover{background-color:#1a1c1f}\n"] }]
1953
2559
  }], propDecorators: { contentIcon: [{
1954
2560
  type: ViewChild,
1955
2561
  args: ['legendsListIcon', { static: false }]
@@ -1971,20 +2577,49 @@ class FeatureLoaderService {
1971
2577
  _featureHelper = inject(FeatureHelperService);
1972
2578
  fomatter = new GeoJSON({ featureProjection: 'EPSG:25832', dataProjection: 'EPSG:25832' });
1973
2579
  loadFeaturesSettings(settings) {
2580
+ if (!settings || !settings.geometryTypeSettings) {
2581
+ return;
2582
+ }
1974
2583
  const profile = this._current.profile;
2584
+ if (!settings || !settings.geometryTypeSettings)
2585
+ return;
1975
2586
  const allTheFeatures = settings.geometryTypeSettings.filter(gt => gt.features).map(gt => {
1976
2587
  const rawFeatures = this.fomatter.readFeatures(gt.features);
1977
2588
  rawFeatures.forEach(f => {
1978
2589
  this._featureHelper.setId(f);
1979
2590
  this._featureHelper.setTypeId(f, gt.typeId);
2591
+ if (gt.disableEditFeatures) {
2592
+ this._featureHelper.lock(f);
2593
+ }
1980
2594
  f.set('STYLENAME', gt.style);
2595
+ if (gt.showLabelFromProperty) {
2596
+ f.set('showlabelfrom', gt.showLabelFromProperty);
2597
+ }
1981
2598
  });
1982
2599
  return rawFeatures;
1983
2600
  }).flatMap(f => f);
1984
2601
  const getAllStyles$ = allTheFeatures.map(f => this._settingsHelper.getStyle(f.get('STYLENAME'), profile?.styleRepositoryWorkspace, profile?.styleRepositoryGeoserver, f.getGeometry().getType()));
1985
2602
  combineLatest(getAllStyles$).subscribe({
1986
2603
  next: styles => {
1987
- styles.forEach((s, i) => allTheFeatures[i].setStyle(s));
2604
+ styles.forEach((s, i) => {
2605
+ const feature = allTheFeatures[i];
2606
+ if (feature.get('showlabelfrom')) {
2607
+ const styles = Array.isArray(s) ? s : [s];
2608
+ const textStyle = new Text({
2609
+ font: '14px Calibri,sans-serif',
2610
+ fill: new Fill({ color: '#000' }),
2611
+ stroke: new Stroke({ color: '#fff', width: 3 }),
2612
+ textAlign: 'center',
2613
+ text: feature.get(feature.get('showlabelfrom'))
2614
+ });
2615
+ const styleText = new Style({ text: textStyle });
2616
+ styles.push(styleText);
2617
+ feature.setStyle(styles);
2618
+ }
2619
+ else {
2620
+ feature.setStyle(s);
2621
+ }
2622
+ });
1988
2623
  this._drawHelperService.setFeatures(allTheFeatures);
1989
2624
  this._zoom.zoomToFeatures(allTheFeatures);
1990
2625
  this._undoRedo.init();
@@ -2027,10 +2662,13 @@ class GisKomponentComponent {
2027
2662
  profiles = [];
2028
2663
  selectedProfile;
2029
2664
  profileShowToolbox = false;
2030
- _highlightService = inject(highlightService);
2665
+ _highlightService = inject(HighlightService);
2031
2666
  _currentItems = inject(CurrentItemsService);
2032
2667
  layers = [];
2033
- mousePositionCtrl = new ol_control_mouse({ projection: 'EPSG:25832' });
2668
+ mousePositionCtrl = new ol_control_mouse({
2669
+ projection: 'EPSG:25832',
2670
+ coordinateFormat: createStringXY(2)
2671
+ });
2034
2672
  onMoveEndCheckZoomFunction = () => { };
2035
2673
  currentZoomLevel = 0;
2036
2674
  scaleCtrl = new ol_control_scale({
@@ -2061,16 +2699,17 @@ class GisKomponentComponent {
2061
2699
  layers: lg.layers
2062
2700
  .filter(layer => layer.activeInSelector)
2063
2701
  .sort((a, b) => a.sortOrder - b.sortOrder)
2064
- .map((l, index) => this._mapLayer(l, capabilityObject, 'EPSG:25832', lg.id, index)) // for now, we default to EPSG:25832.
2702
+ .map((l, index) => this._mapLayer(l, capabilityObject, 'EPSG:25832', lg.id, index)), // for now, we default to EPSG:25832.
2703
+ properties: { id: lg.id }
2065
2704
  }))
2066
2705
  ];
2067
2706
  this.map.setLayers(layers);
2068
- this.map.addLayer(this._highlightService.highlightLayer);
2069
2707
  if (this.settings) {
2070
2708
  this._featureLoader.loadFeaturesSettings(this.settings);
2071
2709
  }
2072
2710
  this._currentItems.map = this.map;
2073
2711
  this._layerHelper.applyCachedLayersToDisplayInMap(this.map, profile.id);
2712
+ this.map.addLayer(this._highlightService.highlightLayer);
2074
2713
  }
2075
2714
  });
2076
2715
  const toolbarControl = new Control({
@@ -2094,7 +2733,6 @@ class GisKomponentComponent {
2094
2733
  this._checkZoom(this.map);
2095
2734
  };
2096
2735
  this.map.on('moveend', this.onMoveEndCheckZoomFunction);
2097
- this._currentItems.map = this.map;
2098
2736
  }
2099
2737
  });
2100
2738
  }
@@ -2215,6 +2853,24 @@ class GisKomponentComponent {
2215
2853
  target: 'map',
2216
2854
  });
2217
2855
  this.map.addControl(new Rotate({ autoHide: false }));
2856
+ this._addRotateControl();
2857
+ }
2858
+ // Added custom north-arrow with a compass one
2859
+ _addRotateControl() {
2860
+ const iconElement = document.createElement('span');
2861
+ iconElement.innerHTML = `
2862
+ <svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2863
+ <path d="M12 3 L16 10 L12 8 L8 10 Z" fill="currentColor"/>
2864
+ <path d="M12 21 L8 14 L12 16 L16 14 Z" fill="currentColor"/>
2865
+ <circle cx="12" cy="12" r="1.5" fill="currentColor"/>
2866
+ </svg>
2867
+ `;
2868
+ const rotateControl = new Rotate({
2869
+ label: iconElement,
2870
+ tipLabel: 'Reset to north',
2871
+ autoHide: false
2872
+ });
2873
+ this.map.addControl(rotateControl);
2218
2874
  }
2219
2875
  toggleShowConflicts() {
2220
2876
  this.showConflicts = !this.showConflicts;
@@ -2232,11 +2888,11 @@ class GisKomponentComponent {
2232
2888
  this.activeObjectsCollapsed = !this.activeObjectsCollapsed;
2233
2889
  }
2234
2890
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: GisKomponentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2235
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: GisKomponentComponent, isStandalone: true, selector: "gis-komponent", inputs: { showToolbox: "showToolbox", showActiveObjects: "showActiveObjects", showLegendList: "showLegendList", showMapSearch: "showMapSearch", identifier: "identifier", settings: "settings" }, providers: [LayerHelperService], viewQueries: [{ propertyName: "toolbarRef", first: true, predicate: ["toolbarRef"], descendants: true, static: true }, { propertyName: "activeObjectsRef", first: true, predicate: ["activeObjectsRef"], descendants: true, static: true }], ngImport: i0, template: "<lib-layer-selector [map]=\"map\" [profile]=\"selectedProfile\" [currentZoomLevel]=\"currentZoomLevel\"></lib-layer-selector>\n<lib-legends-list [map]=\"map\" [profile]=\"selectedProfile\"></lib-legends-list>\n<!-- <span>Zoom: {{ currentZoomLevel}}</span> -->\n<div #activeObjectsRef>\n @if(showActiveObjects && activeObjectsReady && settings) {\n <activeObjects [settings]=\"settings\"></activeObjects>\n }\n</div>\n<div #toolbarRef class=\"map-toolbar-container\">\n @if(showToolbox && profileShowToolbox && settings) {\n <map-toolbox [map]=\"map\" \n [profile]=\"selectedProfile\"\n [settings]=\"settings\"\n [collapsed]=\"selectedProfile.toolbarCollapsed\" [WKTInputEnabled]=\"settings?.WKTInputEnabled\" [deleteEnabled]=\"settings?.deleteEnabled\" [showMeasureArea]=\"selectedProfile.showAreaMeasurement\" [showMeasureDistance]=\"selectedProfile.showDistanceMeasurement\"></map-toolbox>\n }\n</div>\n\n<div class=\"map-container\">\n <lib-map-search *ngIf=\"showMapSearch\"></lib-map-search>\n\n <!-- Objektvisning -->\n <!-- @if (showObjects) {\n <div class=\"object-panel\" [class.collapsed]=\"activeObjectsCollapsed\">\n <div class=\"header\" (click)=\"toggleActiveObjectsCollapsed()\">\n <span>Aktive objekter ({{activeObjects.length}})</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\n </div>\n @if (!activeObjectsCollapsed){\n <ul>\n <li *ngFor=\"let obj of activeObjects\">{{ obj.name }} ({{obj.size}})</li>\n </ul>\n }\n </div>\n } -->\n\n <!-- Konflikter -->\n @if (showConflicts) {\n\n <div class=\"conflict-panel\" [class.collapsed]=\"conflictsCollapsed\">\n <div class=\"header\">\n <span>Konflikter (3)</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon> -->\n </div>\n <mat-list>\n <mat-list-item>\n <span matListItemTitle>Lag #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #2 (svarer ikke)</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #3</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #2</span>\n </mat-list-item>\n </mat-list>\n </div>\n \n } \n\n <!-- Kort -->\n <div id=\"map\" class=\"map\"></div>\n</div>\n", styles: ["::ng-deep .lib-error-snackbar{background-color:#d32f2f;color:#fff;font-weight:500}::ng-deep .map-container{position:relative;height:85vh;width:100%}::ng-deep #map{width:100%;height:100%;position:absolute;inset:0}::ng-deep ::ng-deep .ol-logo{position:absolute;left:auto;right:3em;top:6.25em}::ng-deep ::ng-deep .ol-copyright{background-color:transparent;position:absolute;bottom:10px;width:100%;text-align:center}::ng-deep ::ng-deep .toolbar{position:absolute;top:10px;left:10px;background:#fff;padding:4px;border-radius:4px;display:flex;flex-direction:column;transition:width .3s;z-index:1000}::ng-deep ::ng-deep .toolbar.collapsed{width:40px;overflow:hidden}::ng-deep .object-panel{position:absolute;bottom:10px;left:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000}::ng-deep .object-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep .conflict-panel{position:absolute;bottom:10px;right:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000}::ng-deep .conflict-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep ::ng-deep .ol-zoom.ol-unselectable.ol-control{display:flex;flex-direction:column;position:absolute;top:2rem;left:1rem}::ng-deep ::ng-deep button.ol-zoom-in{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff}::ng-deep ::ng-deep button.ol-zoom-in:hover{color:#e9e3e3;outline:none}::ng-deep button.ol-zoom-out{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff}::ng-deep button.ol-zoom-out:hover{color:#e9e3e3;outline:none}::ng-deep button.ol-rotate-reset{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff}::ng-deep button.ol-rotate-reset:hover{color:#e9e3e3;outline:none}::ng-deep .ol-scale-bar.ol-unselectable{position:absolute;bottom:1rem;left:1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3$2.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i3$2.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i3$2.MatListItemTitle, selector: "[matListItemTitle]" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: LayerSelectorComponent, selector: "lib-layer-selector", inputs: ["map", "profile", "currentZoomLevel"] }, { kind: "component", type: MapSearchComponent, selector: "lib-map-search" }, { kind: "component", type: ToolboxComponent, selector: "map-toolbox", inputs: ["map", "showMeasureDistance", "showMeasureArea", "collapsed", "settings", "profile", "WKTInputEnabled", "deleteEnabled"] }, { kind: "component", type: ActiveObjectsComponent, selector: "activeObjects", inputs: ["settings"] }, { kind: "component", type: LegendsListComponent, selector: "lib-legends-list", inputs: ["map", "profile"] }] });
2891
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: GisKomponentComponent, isStandalone: true, selector: "gis-komponent", inputs: { showToolbox: "showToolbox", showActiveObjects: "showActiveObjects", showLegendList: "showLegendList", showMapSearch: "showMapSearch", identifier: "identifier", settings: "settings" }, providers: [LayerHelperService], viewQueries: [{ propertyName: "toolbarRef", first: true, predicate: ["toolbarRef"], descendants: true, static: true }, { propertyName: "activeObjectsRef", first: true, predicate: ["activeObjectsRef"], descendants: true, static: true }], ngImport: i0, template: "@if (selectedProfile && selectedProfile.showLayerSelector) {\n <lib-layer-selector [map]=\"map\" [profile]=\"selectedProfile\" [currentZoomLevel]=\"currentZoomLevel\"></lib-layer-selector>\n}\n@if (selectedProfile && selectedProfile.showLegends) {\n <lib-legends-list [map]=\"map\" [profile]=\"selectedProfile\"></lib-legends-list>\n}\n\n<!-- <span>Zoom: {{ currentZoomLevel}}</span> -->\n<div #activeObjectsRef>\n @if(showActiveObjects && activeObjectsReady && settings) {\n <activeObjects [settings]=\"settings\"></activeObjects>\n }\n</div>\n<div #toolbarRef class=\"map-toolbar-container\">\n @if(showToolbox && profileShowToolbox && settings) {\n <map-toolbox [map]=\"map\" \n [profile]=\"selectedProfile\"\n [settings]=\"settings\"\n [collapsed]=\"selectedProfile.toolbarCollapsed\" [WKTInputEnabled]=\"settings?.WKTInputEnabled\" [deleteEnabled]=\"settings?.deleteEnabled\" [showMeasureArea]=\"selectedProfile.showAreaMeasurement\" [showMeasureDistance]=\"selectedProfile.showDistanceMeasurement\"></map-toolbox>\n }\n</div>\n\n<div class=\"map-container\">\n <lib-map-search *ngIf=\"showMapSearch\" [profile]=\"selectedProfile\"></lib-map-search>\n\n <!-- Objektvisning -->\n <!-- @if (showObjects) {\n <div class=\"object-panel\" [class.collapsed]=\"activeObjectsCollapsed\">\n <div class=\"header\" (click)=\"toggleActiveObjectsCollapsed()\">\n <span>Aktive objekter ({{activeObjects.length}})</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\n </div>\n @if (!activeObjectsCollapsed){\n <ul>\n <li *ngFor=\"let obj of activeObjects\">{{ obj.name }} ({{obj.size}})</li>\n </ul>\n }\n </div>\n } -->\n\n <!-- Konflikter -->\n @if (showConflicts) {\n\n <div class=\"conflict-panel\" [class.collapsed]=\"conflictsCollapsed\">\n <div class=\"header\">\n <span>Konflikter (3)</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon> -->\n </div>\n <mat-list>\n <mat-list-item>\n <span matListItemTitle>Lag #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #2 (svarer ikke)</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #3</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #2</span>\n </mat-list-item>\n </mat-list>\n </div>\n \n } \n\n <!-- Kort -->\n <div id=\"map\" class=\"map\"></div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;overflow:hidden}::ng-deep .lib-error-snackbar{background-color:#d32f2f;color:#fff;font-weight:500}::ng-deep .map-container{position:relative;height:81vh;width:100%;overflow:hidden}::ng-deep #map{width:100%;height:100%;position:absolute;inset:0;overflow:hidden}::ng-deep .ol-viewport{overflow:hidden!important}::ng-deep ::ng-deep .ol-logo{position:absolute;left:auto;right:3em;top:6.25em}::ng-deep ::ng-deep .ol-copyright{background-color:transparent;position:absolute;bottom:10px;width:100%;text-align:center}::ng-deep ::ng-deep .toolbar{position:absolute;top:10px;left:10px;background:#fff;padding:4px;border-radius:4px;display:flex;flex-direction:column;transition:width .3s;z-index:1000;overflow:hidden}::ng-deep ::ng-deep .toolbar.collapsed{width:40px;overflow:hidden}::ng-deep .object-panel{position:absolute;bottom:10px;left:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000;max-height:calc(85vh - 20px);overflow-y:auto}::ng-deep .object-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep .conflict-panel{position:absolute;bottom:10px;right:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000;max-height:calc(85vh - 20px);overflow-y:auto}::ng-deep .conflict-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep ::ng-deep .ol-zoom.ol-unselectable.ol-control{display:flex;flex-direction:column;position:absolute;left:1rem}::ng-deep ::ng-deep button.ol-zoom-in{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;border-radius:5px 5px 0 0!important;color:#fff}::ng-deep ::ng-deep button.ol-zoom-in:hover{color:#e9e3e3;outline:none}::ng-deep ::ng-deep .ol-scale-text{display:flex}::ng-deep button.ol-zoom-out{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff;border-radius:0 0 5px 5px!important}::ng-deep button.ol-zoom-out:hover{color:#e9e3e3;outline:none}::ng-deep button.ol-rotate-reset{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff;border-radius:5px}::ng-deep button.ol-rotate-reset:hover{color:#e9e3e3;outline:none}::ng-deep .ol-scale-bar.ol-unselectable{position:absolute;bottom:3rem;left:1rem}::ng-deep .ol-mouse-position{top:44em;left:12px;position:absolute;background:color-mix(in srgb,#000 21%,transparent);color:#fffcfc;width:189px;height:30px;padding:2px;border-radius:5px;font-family:Avenir Next W01,Lato,-apple-system,system-ui,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;text-align:center;display:flex;align-items:center;justify-content:flex-start}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i3$1.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i3$1.MatListItemTitle, selector: "[matListItemTitle]" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: LayerSelectorComponent, selector: "lib-layer-selector", inputs: ["map", "profile", "currentZoomLevel"] }, { kind: "component", type: MapSearchComponent, selector: "lib-map-search", inputs: ["profile"] }, { kind: "component", type: ToolboxComponent, selector: "map-toolbox", inputs: ["map", "showMeasureDistance", "showMeasureArea", "collapsed", "settings", "profile", "WKTInputEnabled", "deleteEnabled"] }, { kind: "component", type: ActiveObjectsComponent, selector: "activeObjects", inputs: ["settings"] }, { kind: "component", type: LegendsListComponent, selector: "lib-legends-list", inputs: ["map", "profile"] }] });
2236
2892
  }
2237
2893
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: GisKomponentComponent, decorators: [{
2238
2894
  type: Component,
2239
- args: [{ selector: 'gis-komponent', imports: [CommonModule, MatIconModule, MatListModule, MatSelectModule, LayerSelectorComponent, MapSearchComponent, ToolboxComponent, ActiveObjectsComponent, LegendsListComponent], providers: [LayerHelperService], template: "<lib-layer-selector [map]=\"map\" [profile]=\"selectedProfile\" [currentZoomLevel]=\"currentZoomLevel\"></lib-layer-selector>\n<lib-legends-list [map]=\"map\" [profile]=\"selectedProfile\"></lib-legends-list>\n<!-- <span>Zoom: {{ currentZoomLevel}}</span> -->\n<div #activeObjectsRef>\n @if(showActiveObjects && activeObjectsReady && settings) {\n <activeObjects [settings]=\"settings\"></activeObjects>\n }\n</div>\n<div #toolbarRef class=\"map-toolbar-container\">\n @if(showToolbox && profileShowToolbox && settings) {\n <map-toolbox [map]=\"map\" \n [profile]=\"selectedProfile\"\n [settings]=\"settings\"\n [collapsed]=\"selectedProfile.toolbarCollapsed\" [WKTInputEnabled]=\"settings?.WKTInputEnabled\" [deleteEnabled]=\"settings?.deleteEnabled\" [showMeasureArea]=\"selectedProfile.showAreaMeasurement\" [showMeasureDistance]=\"selectedProfile.showDistanceMeasurement\"></map-toolbox>\n }\n</div>\n\n<div class=\"map-container\">\n <lib-map-search *ngIf=\"showMapSearch\"></lib-map-search>\n\n <!-- Objektvisning -->\n <!-- @if (showObjects) {\n <div class=\"object-panel\" [class.collapsed]=\"activeObjectsCollapsed\">\n <div class=\"header\" (click)=\"toggleActiveObjectsCollapsed()\">\n <span>Aktive objekter ({{activeObjects.length}})</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\n </div>\n @if (!activeObjectsCollapsed){\n <ul>\n <li *ngFor=\"let obj of activeObjects\">{{ obj.name }} ({{obj.size}})</li>\n </ul>\n }\n </div>\n } -->\n\n <!-- Konflikter -->\n @if (showConflicts) {\n\n <div class=\"conflict-panel\" [class.collapsed]=\"conflictsCollapsed\">\n <div class=\"header\">\n <span>Konflikter (3)</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon> -->\n </div>\n <mat-list>\n <mat-list-item>\n <span matListItemTitle>Lag #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #2 (svarer ikke)</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #3</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #2</span>\n </mat-list-item>\n </mat-list>\n </div>\n \n } \n\n <!-- Kort -->\n <div id=\"map\" class=\"map\"></div>\n</div>\n", styles: ["::ng-deep .lib-error-snackbar{background-color:#d32f2f;color:#fff;font-weight:500}::ng-deep .map-container{position:relative;height:85vh;width:100%}::ng-deep #map{width:100%;height:100%;position:absolute;inset:0}::ng-deep ::ng-deep .ol-logo{position:absolute;left:auto;right:3em;top:6.25em}::ng-deep ::ng-deep .ol-copyright{background-color:transparent;position:absolute;bottom:10px;width:100%;text-align:center}::ng-deep ::ng-deep .toolbar{position:absolute;top:10px;left:10px;background:#fff;padding:4px;border-radius:4px;display:flex;flex-direction:column;transition:width .3s;z-index:1000}::ng-deep ::ng-deep .toolbar.collapsed{width:40px;overflow:hidden}::ng-deep .object-panel{position:absolute;bottom:10px;left:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000}::ng-deep .object-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep .conflict-panel{position:absolute;bottom:10px;right:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000}::ng-deep .conflict-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep ::ng-deep .ol-zoom.ol-unselectable.ol-control{display:flex;flex-direction:column;position:absolute;top:2rem;left:1rem}::ng-deep ::ng-deep button.ol-zoom-in{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff}::ng-deep ::ng-deep button.ol-zoom-in:hover{color:#e9e3e3;outline:none}::ng-deep button.ol-zoom-out{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff}::ng-deep button.ol-zoom-out:hover{color:#e9e3e3;outline:none}::ng-deep button.ol-rotate-reset{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff}::ng-deep button.ol-rotate-reset:hover{color:#e9e3e3;outline:none}::ng-deep .ol-scale-bar.ol-unselectable{position:absolute;bottom:1rem;left:1rem}\n"] }]
2895
+ args: [{ selector: 'gis-komponent', imports: [CommonModule, MatIconModule, MatListModule, MatSelectModule, LayerSelectorComponent, MapSearchComponent, ToolboxComponent, ActiveObjectsComponent, LegendsListComponent], providers: [LayerHelperService], template: "@if (selectedProfile && selectedProfile.showLayerSelector) {\n <lib-layer-selector [map]=\"map\" [profile]=\"selectedProfile\" [currentZoomLevel]=\"currentZoomLevel\"></lib-layer-selector>\n}\n@if (selectedProfile && selectedProfile.showLegends) {\n <lib-legends-list [map]=\"map\" [profile]=\"selectedProfile\"></lib-legends-list>\n}\n\n<!-- <span>Zoom: {{ currentZoomLevel}}</span> -->\n<div #activeObjectsRef>\n @if(showActiveObjects && activeObjectsReady && settings) {\n <activeObjects [settings]=\"settings\"></activeObjects>\n }\n</div>\n<div #toolbarRef class=\"map-toolbar-container\">\n @if(showToolbox && profileShowToolbox && settings) {\n <map-toolbox [map]=\"map\" \n [profile]=\"selectedProfile\"\n [settings]=\"settings\"\n [collapsed]=\"selectedProfile.toolbarCollapsed\" [WKTInputEnabled]=\"settings?.WKTInputEnabled\" [deleteEnabled]=\"settings?.deleteEnabled\" [showMeasureArea]=\"selectedProfile.showAreaMeasurement\" [showMeasureDistance]=\"selectedProfile.showDistanceMeasurement\"></map-toolbox>\n }\n</div>\n\n<div class=\"map-container\">\n <lib-map-search *ngIf=\"showMapSearch\" [profile]=\"selectedProfile\"></lib-map-search>\n\n <!-- Objektvisning -->\n <!-- @if (showObjects) {\n <div class=\"object-panel\" [class.collapsed]=\"activeObjectsCollapsed\">\n <div class=\"header\" (click)=\"toggleActiveObjectsCollapsed()\">\n <span>Aktive objekter ({{activeObjects.length}})</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\n </div>\n @if (!activeObjectsCollapsed){\n <ul>\n <li *ngFor=\"let obj of activeObjects\">{{ obj.name }} ({{obj.size}})</li>\n </ul>\n }\n </div>\n } -->\n\n <!-- Konflikter -->\n @if (showConflicts) {\n\n <div class=\"conflict-panel\" [class.collapsed]=\"conflictsCollapsed\">\n <div class=\"header\">\n <span>Konflikter (3)</span>\n <mat-icon>{{ activeObjectsCollapsed ? 'expand_more' : 'expand_less' }}</mat-icon> -->\n </div>\n <mat-list>\n <mat-list-item>\n <span matListItemTitle>Lag #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #2 (svarer ikke)</span>\n </mat-list-item>\n <mat-list-item>\n <span matListItemTitle>Lag #3</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #1</span>\n <span matListItemLine><mat-icon>highlight</mat-icon> Objekt #2</span>\n </mat-list-item>\n </mat-list>\n </div>\n \n } \n\n <!-- Kort -->\n <div id=\"map\" class=\"map\"></div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;overflow:hidden}::ng-deep .lib-error-snackbar{background-color:#d32f2f;color:#fff;font-weight:500}::ng-deep .map-container{position:relative;height:81vh;width:100%;overflow:hidden}::ng-deep #map{width:100%;height:100%;position:absolute;inset:0;overflow:hidden}::ng-deep .ol-viewport{overflow:hidden!important}::ng-deep ::ng-deep .ol-logo{position:absolute;left:auto;right:3em;top:6.25em}::ng-deep ::ng-deep .ol-copyright{background-color:transparent;position:absolute;bottom:10px;width:100%;text-align:center}::ng-deep ::ng-deep .toolbar{position:absolute;top:10px;left:10px;background:#fff;padding:4px;border-radius:4px;display:flex;flex-direction:column;transition:width .3s;z-index:1000;overflow:hidden}::ng-deep ::ng-deep .toolbar.collapsed{width:40px;overflow:hidden}::ng-deep .object-panel{position:absolute;bottom:10px;left:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000;max-height:calc(85vh - 20px);overflow-y:auto}::ng-deep .object-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep .conflict-panel{position:absolute;bottom:10px;right:10px;background:#fff;padding:8px;border-radius:4px;z-index:1000;max-height:calc(85vh - 20px);overflow-y:auto}::ng-deep .conflict-panel .header{display:flex;justify-content:space-between;padding:8px;cursor:pointer;background:#f0f0f0}::ng-deep ::ng-deep .ol-zoom.ol-unselectable.ol-control{display:flex;flex-direction:column;position:absolute;left:1rem}::ng-deep ::ng-deep button.ol-zoom-in{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;border-radius:5px 5px 0 0!important;color:#fff}::ng-deep ::ng-deep button.ol-zoom-in:hover{color:#e9e3e3;outline:none}::ng-deep ::ng-deep .ol-scale-text{display:flex}::ng-deep button.ol-zoom-out{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff;border-radius:0 0 5px 5px!important}::ng-deep button.ol-zoom-out:hover{color:#e9e3e3;outline:none}::ng-deep button.ol-rotate-reset{font-size:2em;width:40px;height:40px;background-color:color-mix(in srgb,#000 60%,transparent);border:none;box-shadow:none;cursor:pointer;color:#fff;border-radius:5px}::ng-deep button.ol-rotate-reset:hover{color:#e9e3e3;outline:none}::ng-deep .ol-scale-bar.ol-unselectable{position:absolute;bottom:3rem;left:1rem}::ng-deep .ol-mouse-position{top:44em;left:12px;position:absolute;background:color-mix(in srgb,#000 21%,transparent);color:#fffcfc;width:189px;height:30px;padding:2px;border-radius:5px;font-family:Avenir Next W01,Lato,-apple-system,system-ui,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;text-align:center;display:flex;align-items:center;justify-content:flex-start}\n"] }]
2240
2896
  }], propDecorators: { showToolbox: [{
2241
2897
  type: Input
2242
2898
  }], showActiveObjects: [{