@vcmap/ui 6.1.0-rc.7 → 6.1.1

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.
Files changed (106) hide show
  1. package/build/bundle.js +3 -3
  2. package/config/base.config.json +7 -3
  3. package/config/cluster.config.json +1 -1
  4. package/config/dev.config.json +172 -56
  5. package/config/projects.config.json +2 -1
  6. package/config/vectorTile.config.json +42 -1
  7. package/dist/assets/cesium.js +1 -1
  8. package/dist/assets/{core-52c2ef11.js → core-5ae90f6d.js} +7515 -5451
  9. package/dist/assets/core.js +1 -1
  10. package/dist/assets/ol.js +1 -1
  11. package/dist/assets/{ui-dccb9009.css → ui-e659989f.css} +1 -1
  12. package/dist/assets/{ui-dccb9009.js → ui-e659989f.js} +21736 -20926
  13. package/dist/assets/ui.js +1 -1
  14. package/dist/assets/vue.js +1 -1
  15. package/dist/assets/{vuetify-43a20e18.css → vuetify-cc6a8213.css} +2 -2
  16. package/dist/assets/{vuetify-43a20e18.js → vuetify-cc6a8213.js} +6694 -6593
  17. package/dist/assets/vuetify.js +1 -1
  18. package/index.d.ts +14 -6
  19. package/index.js +14 -5
  20. package/package.json +18 -9
  21. package/plugins/@vcmap-show-case/vector-properties-example/src/LayerSettings.vue +39 -0
  22. package/plugins/@vcmap-show-case/vector-properties-example/src/VectorPropertiesExample.vue +3 -0
  23. package/plugins/@vcmap-show-case/vector-properties-example/src/lib.js +13 -0
  24. package/plugins/@vcmap-show-case/window-tester/src/WindowExample.vue +9 -0
  25. package/plugins/package.json +9 -5
  26. package/src/actions/actionHelper.d.ts +6 -0
  27. package/src/actions/actionHelper.js +30 -2
  28. package/src/actions/deepPickingAction.d.ts +23 -0
  29. package/src/actions/deepPickingAction.js +404 -0
  30. package/src/actions/extentActions.js +20 -6
  31. package/src/actions/flightActions.js +5 -1
  32. package/src/application/VcsApp.vue +33 -21
  33. package/src/application/VcsApp.vue.d.ts +4 -0
  34. package/src/application/VcsAttributionsFooter.vue +1 -0
  35. package/src/application/VcsContainer.vue +1 -0
  36. package/src/application/VcsContainer.vue.d.ts +4 -0
  37. package/src/application/VcsMobileMenuList.vue +34 -41
  38. package/src/application/VcsNavbar.vue +3 -0
  39. package/src/application/VcsNavbarMobile.vue +6 -18
  40. package/src/application/VcsNavbarMobile.vue.d.ts +0 -1
  41. package/src/application/VcsPositionDisplay.vue +1 -0
  42. package/src/callback/activateLayersCallback.js +9 -1
  43. package/src/callback/addModuleCallback.js +2 -1
  44. package/src/components/buttons/VcsActionButtonList.vue +1 -0
  45. package/src/components/form-inputs-controls/VcsSelect.vue +8 -6
  46. package/src/components/icons/+all.d.ts +5 -0
  47. package/src/components/icons/+all.js +14 -0
  48. package/src/components/lists/VcsActionList.vue +1 -0
  49. package/src/components/lists/VcsGroupedList.vue +2 -1
  50. package/src/components/lists/VcsListItemComponent.vue +1 -0
  51. package/src/components/lists/VcsTreeNode.vue +5 -1
  52. package/src/components/lists/VcsTreeview.vue +14 -2
  53. package/src/components/style/{MenuWrapper.vue → StyleMenuWrapper.vue} +2 -1
  54. package/src/components/style/VcsFillMenu.vue +4 -4
  55. package/src/components/style/VcsImageMenu.vue +4 -4
  56. package/src/components/style/VcsStrokeMenu.vue +4 -4
  57. package/src/components/style/VcsTextMenu.vue +4 -4
  58. package/src/contentTree/LayerTree.vue +8 -46
  59. package/src/contentTree/LayerTree.vue.d.ts +1 -3
  60. package/src/contentTree/contentTreeCollection.d.ts +7 -0
  61. package/src/contentTree/contentTreeCollection.js +30 -10
  62. package/src/contentTree/contentTreeItem.d.ts +4 -4
  63. package/src/contentTree/contentTreeItem.js +2 -2
  64. package/src/contentTree/groupContentTreeItem.d.ts +5 -0
  65. package/src/contentTree/groupContentTreeItem.js +1 -1
  66. package/src/contentTree/layerContentTreeItem.js +1 -1
  67. package/src/contentTree/layerGroupContentTreeItem.js +11 -1
  68. package/src/contentTree/nodeContentTreeItem.d.ts +21 -0
  69. package/src/contentTree/nodeContentTreeItem.js +31 -2
  70. package/src/contentTree/wmsChildContentTreeItem.d.ts +56 -0
  71. package/src/contentTree/wmsChildContentTreeItem.js +159 -0
  72. package/src/contentTree/wmsGroupContentTreeItem.d.ts +171 -0
  73. package/src/contentTree/wmsGroupContentTreeItem.js +620 -0
  74. package/src/featureInfo/ClusterFeatureComponent.vue +47 -11
  75. package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +1 -0
  76. package/src/featureInfo/balloonFeatureInfoView.d.ts +3 -0
  77. package/src/featureInfo/balloonFeatureInfoView.js +78 -11
  78. package/src/featureInfo/balloonHelper.js +8 -12
  79. package/src/featureInfo/featureInfo.d.ts +32 -7
  80. package/src/featureInfo/featureInfo.js +193 -91
  81. package/src/i18n/de.d.ts +22 -16
  82. package/src/i18n/de.js +4 -0
  83. package/src/i18n/en.d.ts +22 -16
  84. package/src/i18n/en.js +4 -0
  85. package/src/legend/legendHelper.d.ts +15 -0
  86. package/src/legend/legendHelper.js +28 -3
  87. package/src/manager/toolbox/GroupToolboxComponent.vue +1 -0
  88. package/src/manager/toolbox/SelectToolboxComponent.vue +2 -0
  89. package/src/manager/toolbox/ToolboxManagerComponent.vue +1 -0
  90. package/src/manager/window/windowManager.d.ts +2 -2
  91. package/src/manager/window/windowManager.js +17 -16
  92. package/src/navigation/MapNavigation.vue +3 -1
  93. package/src/navigation/overviewMap.js +1 -1
  94. package/src/notifier/NotifierComponent.vue +1 -0
  95. package/src/search/ResultsComponent.vue +10 -1
  96. package/src/search/SearchComponent.vue +11 -6
  97. package/src/search/search.js +3 -16
  98. package/src/state.d.ts +2 -1
  99. package/src/state.js +2 -1
  100. package/src/uiConfig.d.ts +9 -0
  101. package/src/uiConfig.js +1 -0
  102. package/src/vcsUiApp.js +7 -1
  103. /package/dist/assets/{cesium-6c6aa853.js → cesium-be8a1422.js} +0 -0
  104. /package/dist/assets/{ol-b0589b0c.js → ol-d5f8aba6.js} +0 -0
  105. /package/dist/assets/{vue-f7a0b088.js → vue-3435e55b.js} +0 -0
  106. /package/src/components/style/{MenuWrapper.vue.d.ts → StyleMenuWrapper.vue.d.ts} +0 -0
@@ -18,13 +18,18 @@ import {
18
18
  alreadyTransformedToImage,
19
19
  ObliqueMap,
20
20
  originalFeatureSymbol,
21
+ mercatorToCartesian,
22
+ cartesianToMercator,
23
+ CesiumMap,
21
24
  } from '@vcmap/core';
22
25
  import { getLogger as getLoggerByName } from '@vcsuite/logger';
23
26
  import {
27
+ Cartographic,
24
28
  Cesium3DTileFeature,
25
29
  Cesium3DTilePointFeature,
26
30
  Color,
27
31
  Entity,
32
+ HeightReference,
28
33
  } from '@vcmap-cesium/engine';
29
34
  import { Feature } from 'ol';
30
35
  import { check, maybe, oneOf } from '@vcsuite/check';
@@ -44,6 +49,7 @@ import { ToolboxType } from '../manager/toolbox/toolboxManager.js';
44
49
  import MarkdownBalloonFeatureInfoView from './markdownBalloonFeatureInfoView.js';
45
50
  import IframeWmsFeatureInfoView from './iframeWmsFeatureInfoView.js';
46
51
  import ClusterFeatureComponent from './ClusterFeatureComponent.vue';
52
+ import { createZoomToFeatureAction } from '../actions/actionHelper.js';
47
53
 
48
54
  /** @typedef {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature|import("@vcmap-cesium/engine").Entity} FeatureType */
49
55
 
@@ -152,6 +158,89 @@ export function getClusterHighlightStyle(
152
158
  return getHighlightStyleFromStyle(clusterStyle, fillColor);
153
159
  }
154
160
 
161
+ /**
162
+ * @param {import("../vcsUiApp.js").default} app
163
+ * @param {import("ol").Feature} feature
164
+ * @returns {import("./abstractFeatureInfoView.js").default|null}
165
+ */
166
+ export function getFeatureInfoViewForFeature(app, feature) {
167
+ if (feature[featureInfoViewSymbol]) {
168
+ return feature[featureInfoViewSymbol];
169
+ }
170
+ const layer = app.layers.getByKey(feature[vcsLayerName]);
171
+ const name = layer?.properties?.featureInfo;
172
+ if (!name) {
173
+ getLogger().debug(
174
+ `No view has been configured for layer '${layer?.name}'.`,
175
+ );
176
+ return null;
177
+ }
178
+ if (!app.featureInfo.hasKey(name)) {
179
+ getLogger().warning(`No view with name '${name}' has been registered.`);
180
+ return null;
181
+ }
182
+ return app.featureInfo.getByKey(name);
183
+ }
184
+
185
+ /**
186
+ * Returns a VcsGroupedListItem for each provided feature and corresponding groups
187
+ * @param {import("../vcsUiApp.js").default} app
188
+ * @param {import("@vcmap/core").EventFeature[]} features
189
+ * @param {import("ol/coordinate.js").Coordinate?} position
190
+ * @returns {{
191
+ * groups: import("../components/lists/VcsGroupedList.vue").VcsListGroup,
192
+ * items: import("../components/lists/VcsGroupedList.vue").VcsGroupedListItem,
193
+ * }}
194
+ */
195
+ export function getGroupedFeatureList(app, features, position = undefined) {
196
+ const groups = {};
197
+ const items = features.map((f) => {
198
+ const oFeature = f[originalFeatureSymbol] ?? f;
199
+ let actions;
200
+ if (oFeature instanceof Feature) {
201
+ actions = [
202
+ createZoomToFeatureAction(
203
+ { name: 'zoomToFeature', icon: 'mdi-target' },
204
+ oFeature,
205
+ app.maps,
206
+ ),
207
+ ];
208
+ }
209
+ /** @type {import("../components/lists/VcsListItemComponent.vue").VcsListItem} */
210
+ const listItem = reactive({
211
+ name: oFeature.getId(),
212
+ title:
213
+ oFeature.getAttributes()?.title ||
214
+ oFeature.getAttributes()?.name ||
215
+ oFeature.getId(),
216
+ disabled: !getFeatureInfoViewForFeature(app, oFeature),
217
+ selectionChanged: (value) => {
218
+ if (value) {
219
+ app.featureInfo
220
+ .selectFeature(oFeature, position)
221
+ .catch((e) => getLogger().error(e));
222
+ } else {
223
+ app.featureInfo.clearFeature();
224
+ }
225
+ },
226
+ actions,
227
+ });
228
+ const layerName = oFeature[vcsLayerName];
229
+ if (layerName) {
230
+ if (!groups[layerName]) {
231
+ const title = app.layers.getByKey(layerName)?.properties?.title;
232
+ groups[layerName] = {
233
+ name: layerName,
234
+ title: title || layerName,
235
+ };
236
+ }
237
+ listItem.group = layerName;
238
+ }
239
+ return listItem;
240
+ });
241
+ return { groups: Object.values(groups), items };
242
+ }
243
+
155
244
  /**
156
245
  * @param {import("../vcsUiApp.js").default} app
157
246
  * @returns {FeatureInfoSession}
@@ -278,6 +367,52 @@ function setupFeatureInfoTool(app) {
278
367
  };
279
368
  }
280
369
 
370
+ /**
371
+ * @param {import("../vcsUiApp.js").default} app
372
+ * @param {import("./balloonFeatureInfoView.js").BalloonFeatureInfoViewProps} props
373
+ * @returns {() => void}
374
+ */
375
+ function setupBalloonHeightListener(app, props) {
376
+ let updateHeightListener = () => {};
377
+ function setupUpdateHeightListener(map) {
378
+ updateHeightListener();
379
+ if (map instanceof CesiumMap) {
380
+ const cartesian = mercatorToCartesian(props.position);
381
+ const cartographic = Cartographic.fromCartesian(cartesian);
382
+ const scene = map.getScene();
383
+ cartographic.height =
384
+ scene.getHeight(cartographic, props.heightReference) +
385
+ props.heightOffset;
386
+ props.position.splice(
387
+ 0,
388
+ Infinity,
389
+ ...cartesianToMercator(Cartographic.toCartesian(cartographic)),
390
+ );
391
+
392
+ updateHeightListener = scene.updateHeight(
393
+ cartographic,
394
+ (clampedCartographic) => {
395
+ const pos = cartesianToMercator(
396
+ Cartographic.toCartesian(clampedCartographic),
397
+ );
398
+ pos[2] += props.heightOffset;
399
+ props.position.splice(0, Infinity, ...pos);
400
+ },
401
+ props.heightReference,
402
+ );
403
+ }
404
+ }
405
+ setupUpdateHeightListener(app.maps.activeMap);
406
+ const mapActivatedListener = app.maps.mapActivated.addEventListener((map) => {
407
+ setupUpdateHeightListener(map);
408
+ });
409
+
410
+ return () => {
411
+ updateHeightListener();
412
+ mapActivatedListener();
413
+ };
414
+ }
415
+
281
416
  /**
282
417
  * @typedef {Object} FeatureInfoSession
283
418
  * @property {VcsEvent<void>} stopped
@@ -317,7 +452,7 @@ class FeatureInfo extends Collection {
317
452
  */
318
453
  this._clusterWindowId = null;
319
454
  /**
320
- * @type {VcsEvent<FeatureType|null>}
455
+ * @type {import("@vcmap/core").VcsEvent<FeatureType|null>}
321
456
  * @private
322
457
  */
323
458
  this._featureChanged = new VcsEvent();
@@ -346,6 +481,12 @@ class FeatureInfo extends Collection {
346
481
  * @private
347
482
  */
348
483
  this._selectedClusterFeatureId = null;
484
+
485
+ /**
486
+ * @type {Array<function():void>}
487
+ * @private
488
+ */
489
+ this._destroyBalloonClampedListener = () => {};
349
490
  /**
350
491
  * @type {Array<function():void>}
351
492
  * @private
@@ -371,24 +512,6 @@ class FeatureInfo extends Collection {
371
512
  ) {
372
513
  this._app.windowManager.remove(this._windowId);
373
514
  }
374
-
375
- if (
376
- this._clusterWindowId &&
377
- this._app.windowManager.has(this._clusterWindowId)
378
- ) {
379
- const { props } = this._app.windowManager.get(this._clusterWindowId);
380
- if (props.items.some((item) => item.group === layer.name)) {
381
- props.items = props.items.filter(
382
- (item) => item.group !== layer.name,
383
- );
384
- props.groups = props.groups.filter(
385
- (group) => group.name !== layer.name,
386
- );
387
- if (props.items.length === 0) {
388
- this._app.windowManager.remove(this._clusterWindowId);
389
- }
390
- }
391
- }
392
515
  }),
393
516
  this._app.windowManager.removed.addEventListener(({ id }) => {
394
517
  if (id === this._windowId) {
@@ -407,7 +530,7 @@ class FeatureInfo extends Collection {
407
530
  ];
408
531
  /**
409
532
  * A vector layer to render provided features on
410
- * @type {VectorLayer|null}
533
+ * @type {import("@vcmap/core").VectorLayer|null}
411
534
  * @private
412
535
  */
413
536
  this._scratchLayer = null;
@@ -421,7 +544,7 @@ class FeatureInfo extends Collection {
421
544
  /**
422
545
  * Emitted whenever a feature is selected or cleared.
423
546
  * Does not reflect cluster feature changes!
424
- * @type {VcsEvent<null|FeatureType>}
547
+ * @type {import("@vcmap/core").VcsEvent<null|FeatureType>}
425
548
  */
426
549
  get featureChanged() {
427
550
  return this._featureChanged;
@@ -443,7 +566,7 @@ class FeatureInfo extends Collection {
443
566
 
444
567
  /**
445
568
  * Emitted whenever a cluster feature is selected or cleared.
446
- * @type {VcsEvent<null|import("ol").Feature>}
569
+ * @type {import("@vcmap/core").VcsEvent<null|import("ol").Feature>}
447
570
  */
448
571
  get clusterFeatureChanged() {
449
572
  return this._clusterFeatureChanged;
@@ -490,29 +613,19 @@ class FeatureInfo extends Collection {
490
613
  });
491
614
  markVolatile(this._scratchLayer);
492
615
  this._app.layers.add(this._scratchLayer);
493
- this._scratchLayer.activate();
616
+ this._scratchLayer.activate().catch((e) => {
617
+ getLogger('FeatureInfo').error('Failed to activate scratch layer', e);
618
+ });
494
619
  }
495
620
  }
496
621
 
497
622
  /**
498
623
  * @param {FeatureType} feature
499
- * @returns {null|AbstractFeatureInfoView}
624
+ * @returns {null|import("./abstractFeatureInfoView.js").default}
500
625
  * @private
501
626
  */
502
627
  _getFeatureInfoViewForFeature(feature) {
503
- const layer = this._app.layers.getByKey(feature[vcsLayerName]);
504
- const name = layer?.properties?.featureInfo;
505
- if (!name) {
506
- getLogger().debug(
507
- `No view has been configured for layer '${layer?.name}'.`,
508
- );
509
- return null;
510
- }
511
- if (!this.hasKey(name)) {
512
- getLogger().warning(`No view with name '${name}' has been registered.`);
513
- return null;
514
- }
515
- return /** @type {AbstractFeatureInfoView} */ this.getByKey(name);
628
+ return getFeatureInfoViewForFeature(this._app, feature);
516
629
  }
517
630
 
518
631
  /**
@@ -525,7 +638,7 @@ class FeatureInfo extends Collection {
525
638
  * @param {FeatureType} feature
526
639
  * @param {import("ol/coordinate.js").Coordinate=} [position] - optional clicked position. If not given feature's center point is used to place balloons
527
640
  * @param {import("ol/coordinate.js").Coordinate=} [windowPosition] - optional clicked window position. If not given derived from position for balloons
528
- * @param {AbstractFeatureInfoView=} featureInfoView
641
+ * @param {import("./abstractFeatureInfoView.js").default=} featureInfoView
529
642
  * @returns {Promise<void>}
530
643
  */
531
644
  async selectFeature(feature, position, windowPosition, featureInfoView) {
@@ -559,6 +672,7 @@ class FeatureInfo extends Collection {
559
672
  // we need to clone the feature to avoid changing vcsLayerNameSymbol on the original feature
560
673
  const clonedFeature = feature.clone();
561
674
  clonedFeature.setId(feature.getId());
675
+ clonedFeature.set('olcs_allowPicking', true);
562
676
  this._scratchLayer.addFeatures([clonedFeature]);
563
677
  const featureId = clonedFeature.getId(); // make sure to grab ID after adding it to the layer
564
678
  this._scratchLayer.featureVisibility.highlight({
@@ -573,17 +687,17 @@ class FeatureInfo extends Collection {
573
687
  this._scratchLayer.featureVisibility.unHighlight([featureId]);
574
688
  } else if (layer.vectorClusterGroup) {
575
689
  this._ensureScratchLayer();
576
- const clone = feature.clone();
690
+ const clonedFeature = feature.clone();
577
691
  const featureId = feature.getId();
578
692
  this._scratchLayer.vectorProperties.setValuesForFeatures(
579
- layer.vectorProperties.getValuesForFeatures([clone]),
580
- [clone],
693
+ layer.vectorProperties.getValuesForFeatures([clonedFeature]),
694
+ [clonedFeature],
581
695
  );
582
- const eyeOffset = clone.get('olcs_eyeOffset') ?? [0, 0, 0];
696
+ const eyeOffset = clonedFeature.get('olcs_eyeOffset') ?? [0, 0, 0];
583
697
  eyeOffset[2] -= 10;
584
- clone.set('olcs_eyeOffset', eyeOffset);
585
- clone.setId(featureId);
586
- this._scratchLayer.addFeatures([clone]);
698
+ clonedFeature.set('olcs_eyeOffset', eyeOffset);
699
+ clonedFeature.setId(featureId);
700
+ this._scratchLayer.addFeatures([clonedFeature]);
587
701
  this._scratchLayer.featureVisibility.highlight({
588
702
  [featureId]: getHighlightStyle(
589
703
  feature,
@@ -593,7 +707,7 @@ class FeatureInfo extends Collection {
593
707
  ),
594
708
  });
595
709
  this._clearHighlightingCb = () =>
596
- this._scratchLayer.featureVisibility.unHighlight([clone]);
710
+ this._scratchLayer.featureVisibility.unHighlight([clonedFeature]);
597
711
  } else if (layer.featureVisibility) {
598
712
  const featureId = feature.getId();
599
713
  layer.featureVisibility.highlight({
@@ -608,14 +722,31 @@ class FeatureInfo extends Collection {
608
722
  layer.featureVisibility.unHighlight([featureId]);
609
723
  }
610
724
  this._windowId = usedFeatureInfoView.className; // use className for a type based position caching
725
+ const windowComponentOptions =
726
+ usedFeatureInfoView.getWindowComponentOptions(
727
+ this._app,
728
+ { feature, position, windowPosition },
729
+ layer,
730
+ );
731
+
732
+ let { props } = windowComponentOptions;
733
+ // check if Balloon should be Rendered Relative or ClampedTo Ground
734
+ if (usedFeatureInfoView instanceof BalloonFeatureInfoView) {
735
+ props = reactive(props);
736
+ if (
737
+ windowComponentOptions.props.heightReference !== HeightReference.NONE
738
+ ) {
739
+ this._destroyBalloonClampedListener = setupBalloonHeightListener(
740
+ this._app,
741
+ props,
742
+ );
743
+ }
744
+ }
611
745
  this._app.windowManager.add(
612
746
  {
613
747
  id: this._windowId,
614
- ...usedFeatureInfoView.getWindowComponentOptions(
615
- this._app,
616
- { feature, position, windowPosition },
617
- layer,
618
- ),
748
+ ...windowComponentOptions,
749
+ props,
619
750
  },
620
751
  vcsAppSymbol,
621
752
  );
@@ -645,8 +776,8 @@ class FeatureInfo extends Collection {
645
776
  const id = `cluster-at-${clusterFeature.getGeometry().getCoordinates().join('-')}`;
646
777
 
647
778
  this._ensureScratchLayer();
648
- const feature = clusterFeature.clone();
649
- feature.setId(id);
779
+ const clonedFeature = clusterFeature.clone();
780
+ clonedFeature.setId(id);
650
781
 
651
782
  clusterFeature[hidden] = true;
652
783
  clusterFeature.changed();
@@ -660,8 +791,8 @@ class FeatureInfo extends Collection {
660
791
  clusterFeature[vectorClusterGroupName],
661
792
  );
662
793
  this._scratchLayer.vectorProperties.setValuesForFeatures(
663
- clusterGroup.vectorProperties.getValuesForFeatures([feature]),
664
- [feature],
794
+ clusterGroup.vectorProperties.getValuesForFeatures([clonedFeature]),
795
+ [clonedFeature],
665
796
  );
666
797
  const clusterStyle = clusterGroup.styleFunction(clusterFeature, 1);
667
798
  const highlightStyle = getClusterHighlightStyle(
@@ -670,50 +801,20 @@ class FeatureInfo extends Collection {
670
801
  clusterStyle,
671
802
  fillColor,
672
803
  );
673
- feature.setStyle(highlightStyle);
804
+ clonedFeature.setStyle(highlightStyle);
674
805
  } else if (clusterFeature[isProvidedClusterFeature]) {
675
- feature.setStyle(
806
+ clonedFeature.setStyle(
676
807
  fromCesiumColor(Color.fromCssColorString(fillColor)).style,
677
808
  );
678
809
  }
679
810
 
680
811
  if (this._app.maps.activeMap instanceof ObliqueMap) {
681
- feature.getGeometry()[alreadyTransformedToImage] = true;
812
+ clonedFeature.getGeometry()[alreadyTransformedToImage] = true;
682
813
  }
683
- this._scratchLayer.addFeatures([feature]);
814
+ this._scratchLayer.addFeatures([clonedFeature]);
684
815
 
685
816
  const features = clusterFeature.get('features');
686
- const groups = {};
687
- const items = features.map((f) => {
688
- const oFeature = f[originalFeatureSymbol] ?? f;
689
- const listItem = reactive({
690
- name: oFeature.getId(),
691
- title:
692
- oFeature.getAttributes()?.title ||
693
- oFeature.getAttributes()?.name ||
694
- oFeature.getId(),
695
- disabled: !this._getFeatureInfoViewForFeature(oFeature),
696
- selectionChanged: (value) => {
697
- if (value) {
698
- this.selectFeature(oFeature);
699
- } else {
700
- this.clearFeature();
701
- }
702
- },
703
- });
704
- const layerName = oFeature[vcsLayerName];
705
- if (layerName) {
706
- if (!groups[layerName]) {
707
- const title = this._app.layers.getByKey(layerName)?.properties?.title;
708
- groups[layerName] = {
709
- name: layerName,
710
- title: title || layerName,
711
- };
712
- }
713
- listItem.group = layerName;
714
- }
715
- return listItem;
716
- });
817
+ const { items, groups } = getGroupedFeatureList(this._app, features);
717
818
 
718
819
  this._clusterWindowId = id;
719
820
  this._app.windowManager.add(
@@ -722,7 +823,7 @@ class FeatureInfo extends Collection {
722
823
  component: ClusterFeatureComponent,
723
824
  props: reactive({
724
825
  items,
725
- groups: Object.values(groups),
826
+ groups,
726
827
  }),
727
828
  state: {
728
829
  headerTitle: 'featureInfo.cluster.headerTitle',
@@ -742,6 +843,7 @@ class FeatureInfo extends Collection {
742
843
  * @private
743
844
  */
744
845
  _clearInternal() {
846
+ this._destroyBalloonClampedListener();
745
847
  if (this._clearHighlightingCb) {
746
848
  this._clearHighlightingCb();
747
849
  this._clearHighlightingCb = null;
package/src/i18n/de.d.ts CHANGED
@@ -474,10 +474,16 @@ declare namespace messages {
474
474
  let empty_2: string;
475
475
  export { empty_2 as empty };
476
476
  }
477
+ namespace deepPicking {
478
+ let title_18: string;
479
+ export { title_18 as title };
480
+ let headerTitle_1: string;
481
+ export { headerTitle_1 as headerTitle };
482
+ }
477
483
  }
478
484
  export namespace legend {
479
- let title_18: string;
480
- export { title_18 as title };
485
+ let title_19: string;
486
+ export { title_19 as title };
481
487
  let tooltip_5: string;
482
488
  export { tooltip_5 as tooltip };
483
489
  let empty_3: string;
@@ -486,8 +492,8 @@ declare namespace messages {
486
492
  export let defaultLabelText: string;
487
493
  }
488
494
  export namespace search_1 {
489
- let title_19: string;
490
- export { title_19 as title };
495
+ let title_20: string;
496
+ export { title_20 as title };
491
497
  let tooltip_6: string;
492
498
  export { tooltip_6 as tooltip };
493
499
  export let select: string;
@@ -499,38 +505,38 @@ declare namespace messages {
499
505
  }
500
506
  export { search_1 as search };
501
507
  export namespace toolbox {
502
- let title_20: string;
503
- export { title_20 as title };
508
+ let title_21: string;
509
+ export { title_21 as title };
504
510
  let flight_1: string;
505
511
  export { flight_1 as flight };
506
512
  export let miscellaneous: string;
507
513
  }
508
514
  export namespace footer {
509
- let title_21: string;
510
- export { title_21 as title };
515
+ let title_22: string;
516
+ export { title_22 as title };
511
517
  export namespace attributions {
512
- let title_22: string;
513
- export { title_22 as title };
518
+ let title_23: string;
519
+ export { title_23 as title };
514
520
  let tooltip_7: string;
515
521
  export { tooltip_7 as tooltip };
516
522
  let empty_4: string;
517
523
  export { empty_4 as empty };
518
524
  }
519
525
  export namespace imprint {
520
- let title_23: string;
521
- export { title_23 as title };
526
+ let title_24: string;
527
+ export { title_24 as title };
522
528
  let tooltip_8: string;
523
529
  export { tooltip_8 as tooltip };
524
530
  }
525
531
  export namespace dataProtection {
526
- let title_24: string;
527
- export { title_24 as title };
532
+ let title_25: string;
533
+ export { title_25 as title };
528
534
  let tooltip_9: string;
529
535
  export { tooltip_9 as tooltip };
530
536
  }
531
537
  export namespace positionDisplay {
532
- let title_25: string;
533
- export { title_25 as title };
538
+ let title_26: string;
539
+ export { title_26 as title };
534
540
  let projection_2: string;
535
541
  export { projection_2 as projection };
536
542
  }
package/src/i18n/de.js CHANGED
@@ -333,6 +333,10 @@ const messages = {
333
333
  collapse: 'Informationsliste minimieren',
334
334
  empty: 'Keine Informationen verfügbar',
335
335
  },
336
+ deepPicking: {
337
+ title: 'Was ist hier?',
338
+ headerTitle: 'Verfügbare Informationen',
339
+ },
336
340
  },
337
341
  legend: {
338
342
  title: 'Legende',
package/src/i18n/en.d.ts CHANGED
@@ -474,10 +474,16 @@ declare namespace messages {
474
474
  let empty_2: string;
475
475
  export { empty_2 as empty };
476
476
  }
477
+ namespace deepPicking {
478
+ let title_18: string;
479
+ export { title_18 as title };
480
+ let headerTitle_1: string;
481
+ export { headerTitle_1 as headerTitle };
482
+ }
477
483
  }
478
484
  export namespace legend {
479
- let title_18: string;
480
- export { title_18 as title };
485
+ let title_19: string;
486
+ export { title_19 as title };
481
487
  let tooltip_5: string;
482
488
  export { tooltip_5 as tooltip };
483
489
  let empty_3: string;
@@ -486,8 +492,8 @@ declare namespace messages {
486
492
  export let defaultLabelText: string;
487
493
  }
488
494
  export namespace search_1 {
489
- let title_19: string;
490
- export { title_19 as title };
495
+ let title_20: string;
496
+ export { title_20 as title };
491
497
  let tooltip_6: string;
492
498
  export { tooltip_6 as tooltip };
493
499
  export let select: string;
@@ -499,38 +505,38 @@ declare namespace messages {
499
505
  }
500
506
  export { search_1 as search };
501
507
  export namespace toolbox {
502
- let title_20: string;
503
- export { title_20 as title };
508
+ let title_21: string;
509
+ export { title_21 as title };
504
510
  let flight_1: string;
505
511
  export { flight_1 as flight };
506
512
  export let miscellaneous: string;
507
513
  }
508
514
  export namespace footer {
509
- let title_21: string;
510
- export { title_21 as title };
515
+ let title_22: string;
516
+ export { title_22 as title };
511
517
  export namespace attributions {
512
- let title_22: string;
513
- export { title_22 as title };
518
+ let title_23: string;
519
+ export { title_23 as title };
514
520
  let tooltip_7: string;
515
521
  export { tooltip_7 as tooltip };
516
522
  let empty_4: string;
517
523
  export { empty_4 as empty };
518
524
  }
519
525
  export namespace imprint {
520
- let title_23: string;
521
- export { title_23 as title };
526
+ let title_24: string;
527
+ export { title_24 as title };
522
528
  let tooltip_8: string;
523
529
  export { tooltip_8 as tooltip };
524
530
  }
525
531
  export namespace dataProtection {
526
- let title_24: string;
527
- export { title_24 as title };
532
+ let title_25: string;
533
+ export { title_25 as title };
528
534
  let tooltip_9: string;
529
535
  export { tooltip_9 as tooltip };
530
536
  }
531
537
  export namespace positionDisplay {
532
- let title_25: string;
533
- export { title_25 as title };
538
+ let title_26: string;
539
+ export { title_26 as title };
534
540
  let projection_2: string;
535
541
  export { projection_2 as projection };
536
542
  }
package/src/i18n/en.js CHANGED
@@ -333,6 +333,10 @@ const messages = {
333
333
  collapse: 'Collapse information list',
334
334
  empty: 'No information available',
335
335
  },
336
+ deepPicking: {
337
+ title: "What's here?",
338
+ headerTitle: 'Available information',
339
+ },
336
340
  },
337
341
  legend: {
338
342
  title: 'Legend',
@@ -62,6 +62,16 @@ export function getImageSrcFromShape(image: import("ol/style/Image.js").Options)
62
62
  * @property {boolean} [open=true] - panel state of entry
63
63
  * @property {Array<LegendItem>} legend - legend properties
64
64
  */
65
+ /**
66
+ * @param {import("@vcmap/core").StyleItem|undefined} style
67
+ * @returns {Array<LegendItem>|undefined}
68
+ */
69
+ export function getStyleLegend(style: import("@vcmap/core").StyleItem | undefined): Array<LegendItem> | undefined;
70
+ /**
71
+ * @param {import("@vcmap/core").Layer|undefined} layer
72
+ * @returns {Array<LegendItem>|undefined}
73
+ */
74
+ export function getLayerLegend(layer: import("@vcmap/core").Layer | undefined): Array<LegendItem> | undefined;
65
75
  /**
66
76
  *
67
77
  * @param {import("../vcsUiApp.js").default} app
@@ -71,6 +81,11 @@ export function getLegendEntries(app: import("../vcsUiApp.js").default): {
71
81
  entries: import("vue").UnwrapRef<Array<LegendEntry>>;
72
82
  destroy: () => void;
73
83
  };
84
+ /**
85
+ * Symbol set a volatile legend property on a layer or style
86
+ * @type {symbol}
87
+ */
88
+ export const legendSymbol: symbol;
74
89
  /**
75
90
  * *
76
91
  */