@regionerne/gis-komponent 0.0.21 → 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$1 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,7 +12,7 @@ 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
17
  import * as i3$1 from '@angular/material/list';
18
18
  import { MatListModule } from '@angular/material/list';
@@ -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, switchMap, forkJoin, catchError, combineLatest, 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
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 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,10 +572,6 @@ 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
  }
@@ -539,12 +599,12 @@ class LayerSelectorComponent {
539
599
  }));
540
600
  }
541
601
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
542
- 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=\"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\">browser_not_supported</mat-icon>\n <span class=\"icon-label\">(zoom)</span>\n }\n @if (layer.hasErrors) {\n <mat-icon class=\"zoom-off\">wifi_off</mat-icon>\n <span class=\"icon-label\">(fejle)</span>\n }\n </div>\n <div class=\"item-right\">\n @if (layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-on\">power</mat-icon>\n <span class=\"icon-label\">(t\u00E6nd)</span>\n }\n @if (!layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-off\">power_off</mat-icon>\n <span class=\"icon-label\">(sluk)</span>\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=\"item\">{{ 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:1em;bottom:4em;max-width:calc(100vw - 2em)}}.drag-handle-selector{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;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 60%,transparent);box-shadow:0 4px 20px #00000026;width:480px;max-width:100%;max-height:660px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 767px){::ng-deep .layer-selector-body{width:100%;max-height:60vh}}@media (min-width: 768px) and (max-width: 1024px){::ng-deep .layer-selector-body{width:100%;max-width:480px;max-height:50vh}}::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}::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;padding:6px;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(70vh - 80px)}}::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 11px;height:40px;background:color-mix(in srgb,#000 55%,transparent)}@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:#fff;font-size:13px}@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:#fff;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: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}@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 .item{width:100%;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}@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{flex:1;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@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 .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-right .icon-label{font-size:9px;margin-right:2px}}::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: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: 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: 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.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3.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"] }] });
543
603
  }
544
604
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LayerSelectorComponent, decorators: [{
545
605
  type: Component,
546
606
  args: [{ selector: 'lib-layer-selector', imports: [MatFormFieldModule, CommonModule, MatIconModule, FormsModule, DragDropModule,
547
- 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=\"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\">browser_not_supported</mat-icon>\n <span class=\"icon-label\">(zoom)</span>\n }\n @if (layer.hasErrors) {\n <mat-icon class=\"zoom-off\">wifi_off</mat-icon>\n <span class=\"icon-label\">(fejle)</span>\n }\n </div>\n <div class=\"item-right\">\n @if (layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-on\">power</mat-icon>\n <span class=\"icon-label\">(t\u00E6nd)</span>\n }\n @if (!layer.visible) {\n <mat-icon (click)=\"toggleLayer($event, layer)\" class=\"power-off\">power_off</mat-icon>\n <span class=\"icon-label\">(sluk)</span>\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=\"item\">{{ 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:1em;bottom:4em;max-width:calc(100vw - 2em)}}.drag-handle-selector{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;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 60%,transparent);box-shadow:0 4px 20px #00000026;width:480px;max-width:100%;max-height:660px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 767px){::ng-deep .layer-selector-body{width:100%;max-height:60vh}}@media (min-width: 768px) and (max-width: 1024px){::ng-deep .layer-selector-body{width:100%;max-width:480px;max-height:50vh}}::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}::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;padding:6px;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(70vh - 80px)}}::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 11px;height:40px;background:color-mix(in srgb,#000 55%,transparent)}@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:#fff;font-size:13px}@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:#fff;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: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}@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 .item{width:100%;box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}@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{flex:1;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@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 .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-right .icon-label{font-size:9px;margin-right:2px}}::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: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"] }]
548
608
  }], propDecorators: { contentIcon: [{
549
609
  type: ViewChild,
550
610
  args: ['layerSelectorIcon', { static: false }]
@@ -625,7 +685,7 @@ class CurrentItemsService {
625
685
  this._mapSubject.next(value);
626
686
  }
627
687
  profile;
628
- _mapSubject = new ReplaySubject();
688
+ _mapSubject = new ReplaySubject(1);
629
689
  map$ = this._mapSubject.asObservable();
630
690
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CurrentItemsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
631
691
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CurrentItemsService, providedIn: 'root' });
@@ -643,7 +703,8 @@ class DrawLayerSourceService {
643
703
  features$ = this._features.asObservable();
644
704
  source = new VectorSource();
645
705
  layer = new VectorLayer({
646
- source: this.source
706
+ source: this.source,
707
+ zIndex: 999
647
708
  });
648
709
  _disabled = false;
649
710
  constructor() {
@@ -706,9 +767,6 @@ class FeatureHelperService {
706
767
  _idCounter = 0;
707
768
  isLocked = (feature) => feature.get(this.FEATURE_LOCKED) === 'true';
708
769
  lock(feature) { feature.set(this.FEATURE_LOCKED, 'true'); }
709
- constructor() {
710
- console.log('FeatureHelperService, constructor');
711
- }
712
770
  setTypeId(feature, typeId) {
713
771
  feature.set(this.FEATURE_TYPE_ID, typeId);
714
772
  }
@@ -724,7 +782,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
724
782
  args: [{
725
783
  providedIn: 'root'
726
784
  }]
727
- }], ctorParameters: () => [] });
785
+ }] });
728
786
 
729
787
  class UndoRedoService {
730
788
  _drawlayerSourceService;
@@ -812,7 +870,7 @@ class GeometrySplitService {
812
870
  const bufferedLine = buffer(lineGeoJSON, bufferMeters, { units: 'meters' });
813
871
  // Move back to 25832
814
872
  bufferedLine.geometry.coordinates = bufferedLine.geometry.coordinates.map(a => a.map(c => proj4('EPSG:4326', 'EPSG:25832', c)));
815
- 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()));
816
874
  overlappingFeatures.forEach((feature) => {
817
875
  const overlappingFeatureGeoJson = this.geoJsonFormat.writeFeatureObject(feature);
818
876
  const features = featureCollection([overlappingFeatureGeoJson, bufferedLine]);
@@ -867,10 +925,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
867
925
  }]
868
926
  }] });
869
927
 
870
- class highlightService {
871
- constructor() {
872
- console.log('highlightservice, constructor');
873
- }
928
+ class HighlightService {
929
+ _wktFormat = new WKT();
874
930
  _zoomService = inject(ZoomService);
875
931
  _style = new Style({
876
932
  stroke: new Stroke({
@@ -896,7 +952,7 @@ class highlightService {
896
952
  }
897
953
  highlight(feature, zoomToFeatures = true) {
898
954
  if (!Array.isArray(feature)) {
899
- this.highlight([feature]);
955
+ this.highlight([this._ensureFeature(feature)]);
900
956
  return;
901
957
  }
902
958
  // If the feature has a style, it overwrites the style of the layer, so I create a new feature without properties or style.
@@ -905,15 +961,24 @@ class highlightService {
905
961
  this._zoomService.zoomToFeatures(feature);
906
962
  }
907
963
  }
908
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: highlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
909
- 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' });
910
975
  }
911
- 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: [{
912
977
  type: Injectable,
913
978
  args: [{
914
979
  providedIn: 'root'
915
980
  }]
916
- }], ctorParameters: () => [] });
981
+ }] });
917
982
 
918
983
  class InteractionHelperService {
919
984
  _current = inject(CurrentItemsService);
@@ -950,6 +1015,9 @@ class MergeFeaturesService {
950
1015
  formatter = new GeoJSON();
951
1016
  _formatterOptions = { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:25832' };
952
1017
  _selectFilter(f, typeId) {
1018
+ if (this._featureHelper.isLocked(f)) {
1019
+ return false;
1020
+ }
953
1021
  if (this._selectedMergeFeature) {
954
1022
  const previusFeatureObject = this.formatter.writeFeatureObject(this._selectedMergeFeature, this._formatterOptions);
955
1023
  const bufferedPreviouslySelected = buffer(previusFeatureObject, 5, { units: 'centimeters' });
@@ -1023,26 +1091,11 @@ class IconsConstants {
1023
1091
 
1024
1092
  class PrintDrawLayerSourceService {
1025
1093
  _current = inject(CurrentItemsService);
1026
- // private _features = new Subject<Feature[]>;
1027
- // features$ = this._features.asObservable();
1028
1094
  source = new VectorSource();
1029
1095
  layer = new VectorLayer({
1030
1096
  source: this.source,
1031
- style: new Style({
1032
- stroke: new Stroke({
1033
- color: 'blue',
1034
- width: 2
1035
- }),
1036
- text: new Text({
1037
- text: 'MySpecialText',
1038
- font: '12px Calibri,sans-serif',
1039
- fill: new Fill({ color: '#000' }),
1040
- stroke: new Stroke({ color: '#fff', width: 3 }),
1041
- placement: 'line'
1042
- })
1043
- })
1097
+ zIndex: 999
1044
1098
  });
1045
- // private _disabled = false;
1046
1099
  constructor() {
1047
1100
  this.layer.set('PRINTDRAWLAYER', 'true');
1048
1101
  this._initListener();
@@ -1050,15 +1103,9 @@ class PrintDrawLayerSourceService {
1050
1103
  _initListener() {
1051
1104
  this._current.map$.subscribe({
1052
1105
  next: map => {
1053
- console.log("🚀 ~ PrintDrawLayerSourceService ~ _initListener ~ map:", map);
1054
1106
  map.addLayer(this.layer);
1055
1107
  }
1056
1108
  });
1057
- // this.source.on(['addfeature', 'changefeature', 'removefeature'], evt => {
1058
- // if (this._disabled) { return; }
1059
- // const features = this.source.getFeatures();
1060
- // this._features.next(features);
1061
- // });
1062
1109
  }
1063
1110
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1064
1111
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PrintDrawLayerSourceService, providedIn: 'root' });
@@ -1070,6 +1117,203 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1070
1117
  }]
1071
1118
  }], ctorParameters: () => [] });
1072
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
+ });
1176
+ }
1177
+ });
1178
+ }
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
1220
+ });
1221
+ return dialogRef.afterClosed();
1222
+ }
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
+ }
1305
+ }
1306
+ }
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' });
1309
+ }
1310
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: OverlapService, decorators: [{
1311
+ type: Injectable,
1312
+ args: [{
1313
+ providedIn: 'root'
1314
+ }]
1315
+ }] });
1316
+
1073
1317
  class ToolboxComponent {
1074
1318
  // Inputs
1075
1319
  map;
@@ -1088,9 +1332,12 @@ class ToolboxComponent {
1088
1332
  _featureHelper = inject(FeatureHelperService);
1089
1333
  _undoRedo = inject(UndoRedoService);
1090
1334
  _geomSplitService = inject(GeometrySplitService);
1091
- _highlight = inject(highlightService);
1335
+ _highlight = inject(HighlightService);
1092
1336
  _interactionHelper = inject(InteractionHelperService);
1093
1337
  _mergeService = inject(MergeFeaturesService);
1338
+ _centerPointService = inject(CenterPointService);
1339
+ _overlap = inject(OverlapService);
1340
+ _zoomService = inject(ZoomService);
1094
1341
  _POSITION_STORAGE_KEY = 'toolbox_position';
1095
1342
  _current = inject(CurrentItemsService);
1096
1343
  _originalMapWidth = 0;
@@ -1106,7 +1353,7 @@ class ToolboxComponent {
1106
1353
  [800, 600]
1107
1354
  ];
1108
1355
  printDrawLabel = "";
1109
- printDrawTool = "point";
1356
+ printDrawTool = "Point";
1110
1357
  selectedGeometrySetting = undefined;
1111
1358
  undoIconBase64 = IconsConstants.undoIconBase64;
1112
1359
  redoIconBase64 = IconsConstants.redoIconBase64;
@@ -1170,9 +1417,21 @@ class ToolboxComponent {
1170
1417
  next: featureStyle => {
1171
1418
  feature.setStyle(featureStyle);
1172
1419
  this._featureHelper.setTypeId(feature, this.selectedGeometrySetting?.typeId || '');
1173
- this._highlight.highlight(feature);
1174
- const extent = buffer$1(feature.getGeometry().getExtent(), 10);
1175
- 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
+ }
1176
1435
  }
1177
1436
  });
1178
1437
  }
@@ -1184,6 +1443,14 @@ class ToolboxComponent {
1184
1443
  type: 'Polygon',
1185
1444
  source: this._drawLayerService.source
1186
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
+ }
1187
1454
  _actionSource = new VectorSource();
1188
1455
  clipHole() {
1189
1456
  this._clearAllInteractions();
@@ -1194,7 +1461,7 @@ class ToolboxComponent {
1194
1461
  });
1195
1462
  this._interactionHelper.setAsTemp(clipHoleDraw);
1196
1463
  clipHoleDraw.on('drawend', evt => {
1197
- 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()));
1198
1465
  const geoJsonFormat = new GeoJSON();
1199
1466
  const holeGeoJson = geoJsonFormat.writeFeatureObject(evt.feature);
1200
1467
  overlappingFeatures.forEach(f => {
@@ -1264,6 +1531,7 @@ class ToolboxComponent {
1264
1531
  this._interactionHelper.setAsTemp(this.deleteSelect);
1265
1532
  this.deleteSelect.on('select', evt => {
1266
1533
  this._drawLayerService.source.removeFeatures(evt.selected);
1534
+ evt.selected.forEach(f => this._centerPointService.handleFeatureDeleted(f.getId()));
1267
1535
  });
1268
1536
  return this._deleteSelect;
1269
1537
  }
@@ -1280,10 +1548,18 @@ class ToolboxComponent {
1280
1548
  this.activeMode = 'edit-remove';
1281
1549
  const modifyRemove = new Modify({
1282
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
+ },
1283
1559
  // Make sure delete is allowed and other interactions are not.
1284
1560
  deleteCondition: always,
1285
1561
  insertVertexCondition: never,
1286
- snapToPointer: this.snap
1562
+ snapToPointer: this.snap,
1287
1563
  });
1288
1564
  this._interactionHelper.setAsTemp(modifyRemove);
1289
1565
  this.map.addInteraction(modifyRemove);
@@ -1294,10 +1570,18 @@ class ToolboxComponent {
1294
1570
  this.activeMode = 'edit';
1295
1571
  const modify = new Modify({
1296
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
+ },
1297
1581
  // No delete
1298
1582
  deleteCondition: () => false,
1299
1583
  // Allow moving existing and add new points
1300
- condition: always,
1584
+ // condition: always,
1301
1585
  insertVertexCondition: always,
1302
1586
  });
1303
1587
  /* Modify fires changes to features a LOT, so to not flood the UndoRedo service, I disable until ending the modify
@@ -1324,13 +1608,28 @@ class ToolboxComponent {
1324
1608
  next: style => {
1325
1609
  const drawInteraction = new Draw({
1326
1610
  type: geomType,
1327
- source: this._drawLayerService.source,
1611
+ source: new VectorSource(),
1328
1612
  style: style
1329
1613
  });
1614
+ this._undoRedo.disable();
1330
1615
  drawInteraction.on('drawend', evt => {
1331
1616
  this._featureHelper.setTypeId(evt.feature, this.selectedGeometrySetting?.typeId || '');
1332
1617
  this._featureHelper.setId(evt.feature);
1333
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
+ }
1334
1633
  });
1335
1634
  this._interactionHelper.setAsTemp(drawInteraction);
1336
1635
  // this._setDrawLayer()
@@ -1344,6 +1643,7 @@ class ToolboxComponent {
1344
1643
  _areaSource = new VectorSource();
1345
1644
  _areaLayer = new VectorLayer({
1346
1645
  source: this._areaSource,
1646
+ zIndex: 999,
1347
1647
  style: (feature) => {
1348
1648
  const geom = feature.getGeometry();
1349
1649
  const area = getArea(geom);
@@ -1369,6 +1669,7 @@ class ToolboxComponent {
1369
1669
  _distanceLabelSource = new VectorSource();
1370
1670
  _distanceLabelLayer = new VectorLayer({
1371
1671
  source: this._distanceLabelSource,
1672
+ zIndex: 999,
1372
1673
  style: (feature) => {
1373
1674
  return new Style({
1374
1675
  text: new Text({
@@ -1383,6 +1684,7 @@ class ToolboxComponent {
1383
1684
  _distanceSource = new VectorSource();
1384
1685
  _distanceLayer = new VectorLayer({
1385
1686
  source: this._distanceSource,
1687
+ zIndex: 999,
1386
1688
  style: (feature) => {
1387
1689
  const geom = feature.getGeometry();
1388
1690
  const length = getLength(geom);
@@ -1664,32 +1966,84 @@ class ToolboxComponent {
1664
1966
  this._active = 'No';
1665
1967
  this._removePrintDrawToolInteraction();
1666
1968
  this.activeMode = null;
1969
+ this.printDrawTool = 'Point';
1667
1970
  return;
1668
1971
  }
1669
1972
  this._active = 'PrintDraw';
1670
1973
  this._clearAllInteractions();
1671
1974
  this._addPrintDrawToolInteraction();
1672
1975
  this.activeMode = null;
1976
+ this.printDrawTool = 'Point';
1673
1977
  }
1674
1978
  handlePrintDrawToolChanged() {
1675
1979
  if (this.active === 'PrintDraw') {
1676
- this.printDrawTool;
1677
- console.log("🚀 ~ ToolboxComponent ~ handlePrintDrawToolChanged ~ this.printDrawTool:", this.printDrawTool);
1980
+ this._removePrintDrawToolInteraction();
1981
+ this._addPrintDrawToolInteraction();
1678
1982
  }
1679
1983
  }
1984
+ handleClearPrintDrawFeatures() {
1985
+ this._printDrawLayerService.source.clear();
1986
+ }
1680
1987
  printDraw;
1681
1988
  _addPrintDrawToolInteraction() {
1682
1989
  if (this.active === 'PrintDraw') {
1683
- const features = this._printDrawLayerService.source.getFeatures();
1684
- console.log("🚀 ~ ToolboxComponent ~ _addPrintDrawToolInteraction ~ features:", features);
1685
- console.log("🚀 ~ ToolboxComponent ~ _addPrintDrawToolInteraction ~ this._current.map:", this._current.map?.getLayers());
1686
- this.printDraw = new Draw({
1687
- source: this._printDrawLayerService.source,
1688
- type: 'LineString',
1689
- style: this._printDrawStyle
1690
- });
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
+ }
1691
2018
  this.printDraw.on('drawend', evt => {
1692
- evt.feature.setStyle(this._printDrawStyle);
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
+ }
1693
2047
  });
1694
2048
  }
1695
2049
  this.map.addInteraction(this.printDraw);
@@ -1698,55 +2052,49 @@ class ToolboxComponent {
1698
2052
  _removePrintDrawToolInteraction() {
1699
2053
  this.map.removeInteraction(this.printDraw);
1700
2054
  }
1701
- _printDrawStyle = new Style({
1702
- stroke: new Stroke({
1703
- color: 'blue',
1704
- width: 2
1705
- }),
1706
- text: new Text({
1707
- text: 'MySpecialText',
1708
- font: '12px Calibri,sans-serif',
1709
- fill: new Fill({ color: '#000' }),
1710
- stroke: new Stroke({ color: '#fff', width: 3 }),
1711
- placement: 'line'
1712
- })
1713
- });
1714
- styles = {
1715
- Point: {
1716
- 'circle-radius': 5,
1717
- 'circle-fill-color': 'red',
1718
- 'stroke-color': 'yellow',
1719
- 'stroke-width': 2,
1720
- 'fill-color': 'blue',
1721
- },
1722
- LineString: {
1723
- 'circle-radius': 5,
1724
- 'circle-fill-color': 'red',
1725
- 'stroke-color': 'yellow',
1726
- 'stroke-width': 2,
1727
- 'fill-color': 'blue',
1728
- },
1729
- Polygon: {
1730
- 'circle-radius': 5,
1731
- 'circle-fill-color': 'red',
1732
- 'stroke-color': 'yellow',
1733
- 'stroke-width': 2,
1734
- 'fill-color': 'blue',
1735
- },
1736
- Circle: {
1737
- 'circle-radius': 5,
1738
- 'circle-fill-color': 'red',
1739
- 'stroke-color': 'blue',
1740
- 'stroke-width': 2,
1741
- 'fill-color': 'yellow',
1742
- },
1743
- };
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;
2091
+ }
1744
2092
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ToolboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1745
- 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>build_circle</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 </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=\"line\">Linje</option>\n <option value=\"polygon\">Polygon</option>\n <option value=\"cirkel\">Cirkel</option>\n <option value=\"square\">Kvadrat</option>\n <option value=\"rectangle\">Firkant</option>\n </select>\n <button>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}.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:center}.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}.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-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,.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:#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;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: 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$1.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"] }] });
1746
2094
  }
1747
2095
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ToolboxComponent, decorators: [{
1748
2096
  type: Component,
1749
- 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>build_circle</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 </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=\"line\">Linje</option>\n <option value=\"polygon\">Polygon</option>\n <option value=\"cirkel\">Cirkel</option>\n <option value=\"square\">Kvadrat</option>\n <option value=\"rectangle\">Firkant</option>\n </select>\n <button>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}.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:center}.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}.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-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,.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:#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;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"] }]
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"] }]
1750
2098
  }], ctorParameters: () => [], propDecorators: { map: [{
1751
2099
  type: Input,
1752
2100
  args: [{ required: true }]
@@ -1770,12 +2118,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1770
2118
 
1771
2119
  class ActiveObjectsComponent {
1772
2120
  _drawLayerService = inject(DrawLayerSourceService);
2121
+ _centerPointService = inject(CenterPointService);
2122
+ _undoRedo = inject(UndoRedoService);
1773
2123
  features$ = this._drawLayerService.features$;
1774
2124
  collapsed = false;
1775
2125
  settings;
1776
2126
  activeFeatures = [];
1777
2127
  _featureHelper = inject(FeatureHelperService);
1778
- _highlight = inject(highlightService);
2128
+ _highlight = inject(HighlightService);
1779
2129
  _zoomService = inject(ZoomService);
1780
2130
  opacity = 1;
1781
2131
  dragPosition = { x: 0, y: 0 };
@@ -1789,7 +2139,12 @@ class ActiveObjectsComponent {
1789
2139
  .map(ft => ({ featureType: ft,
1790
2140
  display: this.settings.geometryTypeSettings.find(gts => gts.typeId === ft).typeName,
1791
2141
  features: features.filter(f => this._featureHelper.typeId(f) === ft)
1792
- .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
+ })) }));
1793
2148
  this.activeFeatures = [...featuresObj];
1794
2149
  }
1795
2150
  });
@@ -1803,10 +2158,13 @@ class ActiveObjectsComponent {
1803
2158
  }
1804
2159
  return this.settings.sizeInHa ? `(${(getArea(feature.getGeometry()) / 10000).toFixed(2)} ha)` : `(${getArea(feature.getGeometry()).toFixed(2)} m2)`;
1805
2160
  }
2161
+ reset() {
2162
+ this._undoRedo.reset();
2163
+ this.highlightedId = null;
2164
+ this._highlight.clear();
2165
+ this.zoomToAll();
2166
+ }
1806
2167
  zoomToAll() {
1807
- const formatter = new GeoJSON({ dataProjection: 'EPSG:25832', featureProjection: 'EPSG:25832' });
1808
- const allTheFeatures = formatter.writeFeaturesObject(this._drawLayerService.allFeatures);
1809
- console.log("🚀 ~ ActiveObjectsComponent ~ zoomToAll ~ allTheFeatures:", JSON.stringify(allTheFeatures));
1810
2168
  this._zoomService.zoomToFeatures(this._drawLayerService.allFeatures);
1811
2169
  }
1812
2170
  highlight(id) {
@@ -1827,6 +2185,7 @@ class ActiveObjectsComponent {
1827
2185
  }
1828
2186
  delete(id) {
1829
2187
  this._drawLayerService.remove(id);
2188
+ this._centerPointService.handleFeatureDeleted(id);
1830
2189
  this._highlight.clear();
1831
2190
  }
1832
2191
  togglePanel() {
@@ -1858,33 +2217,158 @@ class ActiveObjectsComponent {
1858
2217
  }
1859
2218
  }
1860
2219
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ActiveObjectsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1861
- 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()\">share_reviewsr</mat-icon>\n @if(!collapsed) {\n <h4>Aktive flader</h4>\n }\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 @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: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}.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);border-radius:8px 8px 0 0;padding:4px 8px;cursor:grab}.drag-handle-active-objects h4{margin:0;padding:5px;background:transparent;font-weight:600;color:#fff;flex:1;font-size:16px;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.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:22px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:6px;flex-shrink:0;margin:0}.drag-handle-active-objects .toggle-icon:hover{color:#ffffffb3;background:#1976d214}.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$1.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.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.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"] }] });
1862
2221
  }
1863
2222
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ActiveObjectsComponent, decorators: [{
1864
2223
  type: Component,
1865
- 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()\">share_reviewsr</mat-icon>\n @if(!collapsed) {\n <h4>Aktive flader</h4>\n }\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 @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: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}.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);border-radius:8px 8px 0 0;padding:4px 8px;cursor:grab}.drag-handle-active-objects h4{margin:0;padding:5px;background:transparent;font-weight:600;color:#fff;flex:1;font-size:16px;-webkit-user-select:none;user-select:none;transition:color .2s ease;white-space:nowrap;text-align:center}.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:22px;width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:6px;flex-shrink:0;margin:0}.drag-handle-active-objects .toggle-icon:hover{color:#ffffffb3;background:#1976d214}.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"] }]
1866
2225
  }], ctorParameters: () => [], propDecorators: { settings: [{
1867
2226
  type: Input,
1868
2227
  args: [{ required: true }]
1869
2228
  }] } });
1870
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
+
1871
2312
  class MapSearchComponent {
1872
2313
  searchAddress = '';
1873
- allResults = ['address1', 'address2', 'address3', 'address4'];
2314
+ profile;
2315
+ // allResults = ['address1', 'address2', 'address3', 'address4'];
1874
2316
  filteredResults = [];
1875
2317
  collapsed = true;
1876
2318
  dragPosition = { x: 0, y: 0 };
1877
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);
1878
2327
  ngOnInit() {
2328
+ this._layerHelperService.activeLayersChanged
2329
+ .subscribe(() => this._addWFSSearchLayers());
1879
2330
  this.filterResults();
1880
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
+ }
1881
2362
  }
1882
2363
  filterResults() {
1883
2364
  if (!this.searchAddress) {
1884
2365
  this.filteredResults = [];
1885
2366
  return;
1886
2367
  }
1887
- 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
+ // });
1888
2372
  }
1889
2373
  toggleSearch() {
1890
2374
  this.collapsed = !this.collapsed;
@@ -1893,6 +2377,10 @@ class MapSearchComponent {
1893
2377
  this.filterResults();
1894
2378
  }
1895
2379
  }
2380
+ highlight(wkt, event) {
2381
+ event.stopPropagation();
2382
+ this._highlight.highlight(wkt);
2383
+ }
1896
2384
  onDragEnded(event) {
1897
2385
  const position = event.source.getFreeDragPosition();
1898
2386
  this.dragPosition = position;
@@ -1919,7 +2407,7 @@ class MapSearchComponent {
1919
2407
  }
1920
2408
  }
1921
2409
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MapSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1922
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.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>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\">\n {{ result }}\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}.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}.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}.toggle-icon:hover{color:#2196f3;background:#2196f314}.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: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-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$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.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.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: 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$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"] }] });
1923
2411
  }
1924
2412
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MapSearchComponent, decorators: [{
1925
2413
  type: Component,
@@ -1932,8 +2420,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1932
2420
  MatOptionModule,
1933
2421
  MatIconModule,
1934
2422
  DragDropModule
1935
- ], 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\">\n {{ result }}\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}.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}.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}.toggle-icon:hover{color:#2196f3;background:#2196f314}.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: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-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"] }]
1936
- }] });
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
+ }] } });
1937
2427
 
1938
2428
  class LayerService {
1939
2429
  config = inject(GISKOMPONENT_CONFIG);
@@ -1979,7 +2469,7 @@ class LegendsListComponent {
1979
2469
  _legendsListIconControl;
1980
2470
  _legendsListBody;
1981
2471
  _legendsListBodyControl;
1982
- _layerIdsToDisplayInMapKeyName = 'layerIdsToDisplayInMap';
2472
+ _mapFilteredLayerGroupsKeyName = 'mapFilteredLayerGroups';
1983
2473
  _layerService = inject(LayerService);
1984
2474
  _layerHelperService = inject(LayerHelperService);
1985
2475
  toggleLegendsList() {
@@ -2015,7 +2505,14 @@ class LegendsListComponent {
2015
2505
  if (!this.profile?.id) {
2016
2506
  return of([]);
2017
2507
  }
2018
- const layerIdsCachedToDisplay = localStorage.getItem(`${this._layerIdsToDisplayInMapKeyName}_${this.profile?.id}`)?.split(',').map(Number);
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);
2019
2516
  if (!layerIdsCachedToDisplay) {
2020
2517
  return of([]);
2021
2518
  }
@@ -2053,12 +2550,12 @@ class LegendsListComponent {
2053
2550
  })));
2054
2551
  }
2055
2552
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LegendsListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2056
- 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: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}.legends-list-body-wrapper{position:absolute;left:auto;right:35em;bottom:.2em;z-index:1000;cursor:grab}@media (max-width: 1024px){.legends-list-body-wrapper{right:32em;bottom:5em}}@media (max-width: 768px){.legends-list-body-wrapper{position:fixed;right:3em;left:1em;bottom:5em;width:calc(100% - 7em);max-width:100%}.legends-list-body-wrapper.cdk-drag-dragging{z-index:1002}}@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:center;background:color-mix(in srgb,#000 60%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab;box-shadow:0 -2px 8px #0003}@media (max-width: 768px){.drag-handle-selector{padding:8px}}.drag-handle-selector mat-icon{color:#fff;font-size:20px;width:20px;height:20px}@media (max-width: 768px){.drag-handle-selector mat-icon{font-size:24px;width:24px;height:24px}}::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:290px;max-height:660px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 1024px){::ng-deep .legends-list-body{width:280px}}@media (max-width: 768px){::ng-deep .legends-list-body{width:100%;max-height:60vh;max-height:calc(var(--vh, 1vh) * 60)}}@media (max-width: 480px){::ng-deep .legends-list-body{max-height:70vh;max-height:calc(var(--vh, 1vh) * 70)}}::ng-deep .legends-list-body .item-list{flex:1;overflow-y:auto;padding:6px;max-height:900px}@media (max-width: 768px){::ng-deep .legends-list-body .item-list{padding:8px;max-height:none}}::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:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}@media (max-width: 768px){::ng-deep .legends-list-body .item-list .item{padding:12px 16px;gap:8px}}::ng-deep .legends-list-body .item-list .item:last-child{border-bottom:none}@media (max-width: 768px){::ng-deep .legends-list-body .item-list mat-expansion-panel{margin-bottom:8px}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header{padding:0 8px;height:auto;min-height:48px}::ng-deep .legends-list-body .item-list .legend{padding:8px}::ng-deep .legends-list-body .item-list .legend-thumbnail{max-width:100%;height:auto;max-height:150px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar{width:6px}}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}@media (max-width: 768px){.legend-thumbnail{max-width:100%;max-height:150px;padding:4px}}::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}.display-none{display:none}\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.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3.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 }] });
2057
2554
  }
2058
2555
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: LegendsListComponent, decorators: [{
2059
2556
  type: Component,
2060
2557
  args: [{ selector: 'lib-legends-list', imports: [MatFormFieldModule, CommonModule, MatIconModule, FormsModule, DragDropModule,
2061
- 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: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}.legends-list-body-wrapper{position:absolute;left:auto;right:35em;bottom:.2em;z-index:1000;cursor:grab}@media (max-width: 1024px){.legends-list-body-wrapper{right:32em;bottom:5em}}@media (max-width: 768px){.legends-list-body-wrapper{position:fixed;right:3em;left:1em;bottom:5em;width:calc(100% - 7em);max-width:100%}.legends-list-body-wrapper.cdk-drag-dragging{z-index:1002}}@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:center;background:color-mix(in srgb,#000 60%,transparent);border-radius:4px 4px 0 0;padding:4px;cursor:grab;box-shadow:0 -2px 8px #0003}@media (max-width: 768px){.drag-handle-selector{padding:8px}}.drag-handle-selector mat-icon{color:#fff;font-size:20px;width:20px;height:20px}@media (max-width: 768px){.drag-handle-selector mat-icon{font-size:24px;width:24px;height:24px}}::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:290px;max-height:660px;overflow:hidden;display:flex;flex-direction:column}@media (max-width: 1024px){::ng-deep .legends-list-body{width:280px}}@media (max-width: 768px){::ng-deep .legends-list-body{width:100%;max-height:60vh;max-height:calc(var(--vh, 1vh) * 60)}}@media (max-width: 480px){::ng-deep .legends-list-body{max-height:70vh;max-height:calc(var(--vh, 1vh) * 70)}}::ng-deep .legends-list-body .item-list{flex:1;overflow-y:auto;padding:6px;max-height:900px}@media (max-width: 768px){::ng-deep .legends-list-body .item-list{padding:8px;max-height:none}}::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:6px;padding:8px 12px;background:transparent;transition:all .2s ease;color:#fff;cursor:grab}@media (max-width: 768px){::ng-deep .legends-list-body .item-list .item{padding:12px 16px;gap:8px}}::ng-deep .legends-list-body .item-list .item:last-child{border-bottom:none}@media (max-width: 768px){::ng-deep .legends-list-body .item-list mat-expansion-panel{margin-bottom:8px}::ng-deep .legends-list-body .item-list mat-expansion-panel .mat-expansion-panel-header{padding:0 8px;height:auto;min-height:48px}::ng-deep .legends-list-body .item-list .legend{padding:8px}::ng-deep .legends-list-body .item-list .legend-thumbnail{max-width:100%;height:auto;max-height:150px}::ng-deep .legends-list-body .item-list::-webkit-scrollbar{width:6px}}.legend-thumbnail{max-width:200px;max-height:200px;width:auto;height:auto;border:2px solid #dee2e6;border-radius:6px;padding:6px}@media (max-width: 768px){.legend-thumbnail{max-width:100%;max-height:150px;padding:4px}}::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}.display-none{display:none}\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"] }]
2062
2559
  }], propDecorators: { contentIcon: [{
2063
2560
  type: ViewChild,
2064
2561
  args: ['legendsListIcon', { static: false }]
@@ -2084,19 +2581,45 @@ class FeatureLoaderService {
2084
2581
  return;
2085
2582
  }
2086
2583
  const profile = this._current.profile;
2584
+ if (!settings || !settings.geometryTypeSettings)
2585
+ return;
2087
2586
  const allTheFeatures = settings.geometryTypeSettings.filter(gt => gt.features).map(gt => {
2088
2587
  const rawFeatures = this.fomatter.readFeatures(gt.features);
2089
2588
  rawFeatures.forEach(f => {
2090
2589
  this._featureHelper.setId(f);
2091
2590
  this._featureHelper.setTypeId(f, gt.typeId);
2591
+ if (gt.disableEditFeatures) {
2592
+ this._featureHelper.lock(f);
2593
+ }
2092
2594
  f.set('STYLENAME', gt.style);
2595
+ if (gt.showLabelFromProperty) {
2596
+ f.set('showlabelfrom', gt.showLabelFromProperty);
2597
+ }
2093
2598
  });
2094
2599
  return rawFeatures;
2095
2600
  }).flatMap(f => f);
2096
2601
  const getAllStyles$ = allTheFeatures.map(f => this._settingsHelper.getStyle(f.get('STYLENAME'), profile?.styleRepositoryWorkspace, profile?.styleRepositoryGeoserver, f.getGeometry().getType()));
2097
2602
  combineLatest(getAllStyles$).subscribe({
2098
2603
  next: styles => {
2099
- 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
+ });
2100
2623
  this._drawHelperService.setFeatures(allTheFeatures);
2101
2624
  this._zoom.zoomToFeatures(allTheFeatures);
2102
2625
  this._undoRedo.init();
@@ -2139,10 +2662,13 @@ class GisKomponentComponent {
2139
2662
  profiles = [];
2140
2663
  selectedProfile;
2141
2664
  profileShowToolbox = false;
2142
- _highlightService = inject(highlightService);
2665
+ _highlightService = inject(HighlightService);
2143
2666
  _currentItems = inject(CurrentItemsService);
2144
2667
  layers = [];
2145
- mousePositionCtrl = new ol_control_mouse({ projection: 'EPSG:25832' });
2668
+ mousePositionCtrl = new ol_control_mouse({
2669
+ projection: 'EPSG:25832',
2670
+ coordinateFormat: createStringXY(2)
2671
+ });
2146
2672
  onMoveEndCheckZoomFunction = () => { };
2147
2673
  currentZoomLevel = 0;
2148
2674
  scaleCtrl = new ol_control_scale({
@@ -2173,16 +2699,17 @@ class GisKomponentComponent {
2173
2699
  layers: lg.layers
2174
2700
  .filter(layer => layer.activeInSelector)
2175
2701
  .sort((a, b) => a.sortOrder - b.sortOrder)
2176
- .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 }
2177
2704
  }))
2178
2705
  ];
2179
2706
  this.map.setLayers(layers);
2180
- this.map.addLayer(this._highlightService.highlightLayer);
2181
2707
  if (this.settings) {
2182
2708
  this._featureLoader.loadFeaturesSettings(this.settings);
2183
2709
  }
2184
2710
  this._currentItems.map = this.map;
2185
2711
  this._layerHelper.applyCachedLayersToDisplayInMap(this.map, profile.id);
2712
+ this.map.addLayer(this._highlightService.highlightLayer);
2186
2713
  }
2187
2714
  });
2188
2715
  const toolbarControl = new Control({
@@ -2206,7 +2733,6 @@ class GisKomponentComponent {
2206
2733
  this._checkZoom(this.map);
2207
2734
  };
2208
2735
  this.map.on('moveend', this.onMoveEndCheckZoomFunction);
2209
- this._currentItems.map = this.map;
2210
2736
  }
2211
2737
  });
2212
2738
  }
@@ -2327,6 +2853,24 @@ class GisKomponentComponent {
2327
2853
  target: 'map',
2328
2854
  });
2329
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);
2330
2874
  }
2331
2875
  toggleShowConflicts() {
2332
2876
  this.showConflicts = !this.showConflicts;
@@ -2344,11 +2888,11 @@ class GisKomponentComponent {
2344
2888
  this.activeObjectsCollapsed = !this.activeObjectsCollapsed;
2345
2889
  }
2346
2890
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: GisKomponentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2347
- 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\"></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;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$1.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$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" }, { 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"] }] });
2348
2892
  }
2349
2893
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: GisKomponentComponent, decorators: [{
2350
2894
  type: Component,
2351
- 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\"></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;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"] }]
2352
2896
  }], propDecorators: { showToolbox: [{
2353
2897
  type: Input
2354
2898
  }], showActiveObjects: [{