@vcmap/ui 6.1.0-rc.7 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/config/base.config.json +7 -3
  2. package/config/cluster.config.json +1 -1
  3. package/config/dev.config.json +172 -56
  4. package/config/projects.config.json +2 -1
  5. package/config/vectorTile.config.json +42 -1
  6. package/dist/assets/cesium.js +1 -1
  7. package/dist/assets/{core-52c2ef11.js → core-841b71a4.js} +7544 -5485
  8. package/dist/assets/core.js +1 -1
  9. package/dist/assets/ol.js +1 -1
  10. package/dist/assets/{ui-dccb9009.css → ui-2fd6f47d.css} +1 -1
  11. package/dist/assets/{ui-dccb9009.js → ui-2fd6f47d.js} +21402 -20661
  12. package/dist/assets/ui.js +1 -1
  13. package/dist/assets/vue.js +1 -1
  14. package/dist/assets/{vuetify-43a20e18.css → vuetify-4bc77ff7.css} +2 -2
  15. package/dist/assets/{vuetify-43a20e18.js → vuetify-4bc77ff7.js} +6694 -6593
  16. package/dist/assets/vuetify.js +1 -1
  17. package/index.d.ts +13 -5
  18. package/index.js +13 -5
  19. package/package.json +9 -8
  20. package/plugins/@vcmap-show-case/vector-properties-example/src/LayerSettings.vue +39 -0
  21. package/plugins/@vcmap-show-case/vector-properties-example/src/VectorPropertiesExample.vue +3 -0
  22. package/plugins/@vcmap-show-case/vector-properties-example/src/lib.js +13 -0
  23. package/plugins/@vcmap-show-case/window-tester/src/WindowExample.vue +9 -0
  24. package/plugins/package.json +7 -5
  25. package/src/actions/actionHelper.d.ts +6 -0
  26. package/src/actions/actionHelper.js +22 -0
  27. package/src/actions/deepPickingAction.d.ts +23 -0
  28. package/src/actions/deepPickingAction.js +399 -0
  29. package/src/application/VcsApp.vue +3 -0
  30. package/src/application/VcsApp.vue.d.ts +4 -0
  31. package/src/application/VcsAttributionsFooter.vue +1 -0
  32. package/src/application/VcsContainer.vue +1 -0
  33. package/src/application/VcsContainer.vue.d.ts +4 -0
  34. package/src/application/VcsMobileMenuList.vue +34 -41
  35. package/src/application/VcsNavbar.vue +3 -0
  36. package/src/application/VcsNavbarMobile.vue +6 -18
  37. package/src/application/VcsNavbarMobile.vue.d.ts +0 -1
  38. package/src/application/VcsPositionDisplay.vue +1 -0
  39. package/src/components/buttons/VcsActionButtonList.vue +1 -0
  40. package/src/components/form-inputs-controls/VcsSelect.vue +8 -6
  41. package/src/components/icons/+all.d.ts +5 -0
  42. package/src/components/icons/+all.js +14 -0
  43. package/src/components/lists/VcsActionList.vue +1 -0
  44. package/src/components/lists/VcsGroupedList.vue +2 -1
  45. package/src/components/lists/VcsListItemComponent.vue +1 -0
  46. package/src/components/lists/VcsTreeNode.vue +5 -1
  47. package/src/components/lists/VcsTreeview.vue +4 -1
  48. package/src/components/style/{MenuWrapper.vue → StyleMenuWrapper.vue} +2 -1
  49. package/src/components/style/VcsFillMenu.vue +4 -4
  50. package/src/components/style/VcsImageMenu.vue +4 -4
  51. package/src/components/style/VcsStrokeMenu.vue +4 -4
  52. package/src/components/style/VcsTextMenu.vue +4 -4
  53. package/src/contentTree/LayerTree.vue +8 -46
  54. package/src/contentTree/LayerTree.vue.d.ts +1 -3
  55. package/src/contentTree/contentTreeCollection.d.ts +7 -0
  56. package/src/contentTree/contentTreeCollection.js +30 -10
  57. package/src/contentTree/contentTreeItem.d.ts +4 -4
  58. package/src/contentTree/contentTreeItem.js +2 -2
  59. package/src/contentTree/groupContentTreeItem.d.ts +5 -0
  60. package/src/contentTree/groupContentTreeItem.js +1 -1
  61. package/src/contentTree/layerContentTreeItem.js +1 -1
  62. package/src/contentTree/nodeContentTreeItem.d.ts +21 -0
  63. package/src/contentTree/nodeContentTreeItem.js +31 -2
  64. package/src/contentTree/wmsChildContentTreeItem.d.ts +56 -0
  65. package/src/contentTree/wmsChildContentTreeItem.js +159 -0
  66. package/src/contentTree/wmsGroupContentTreeItem.d.ts +171 -0
  67. package/src/contentTree/wmsGroupContentTreeItem.js +619 -0
  68. package/src/featureInfo/ClusterFeatureComponent.vue +47 -11
  69. package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +1 -0
  70. package/src/featureInfo/balloonFeatureInfoView.d.ts +3 -0
  71. package/src/featureInfo/balloonFeatureInfoView.js +78 -11
  72. package/src/featureInfo/balloonHelper.js +8 -12
  73. package/src/featureInfo/featureInfo.d.ts +32 -7
  74. package/src/featureInfo/featureInfo.js +190 -90
  75. package/src/i18n/de.d.ts +22 -16
  76. package/src/i18n/de.js +4 -0
  77. package/src/i18n/en.d.ts +22 -16
  78. package/src/i18n/en.js +4 -0
  79. package/src/manager/toolbox/GroupToolboxComponent.vue +1 -0
  80. package/src/manager/toolbox/SelectToolboxComponent.vue +2 -0
  81. package/src/manager/toolbox/ToolboxManagerComponent.vue +1 -0
  82. package/src/manager/window/windowManager.d.ts +2 -2
  83. package/src/manager/window/windowManager.js +12 -10
  84. package/src/navigation/MapNavigation.vue +3 -1
  85. package/src/notifier/NotifierComponent.vue +1 -0
  86. package/src/search/search.js +3 -16
  87. package/src/state.d.ts +2 -1
  88. package/src/state.js +2 -1
  89. package/src/uiConfig.d.ts +9 -0
  90. package/src/uiConfig.js +1 -0
  91. /package/dist/assets/{cesium-6c6aa853.js → cesium-664ad022.js} +0 -0
  92. /package/dist/assets/{ol-b0589b0c.js → ol-2e095c08.js} +0 -0
  93. /package/dist/assets/{vue-f7a0b088.js → vue-71fd14e8.js} +0 -0
  94. /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;
@@ -496,23 +619,11 @@ class FeatureInfo extends Collection {
496
619
 
497
620
  /**
498
621
  * @param {FeatureType} feature
499
- * @returns {null|AbstractFeatureInfoView}
622
+ * @returns {null|import("./abstractFeatureInfoView.js").default}
500
623
  * @private
501
624
  */
502
625
  _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);
626
+ return getFeatureInfoViewForFeature(this._app, feature);
516
627
  }
517
628
 
518
629
  /**
@@ -525,7 +636,7 @@ class FeatureInfo extends Collection {
525
636
  * @param {FeatureType} feature
526
637
  * @param {import("ol/coordinate.js").Coordinate=} [position] - optional clicked position. If not given feature's center point is used to place balloons
527
638
  * @param {import("ol/coordinate.js").Coordinate=} [windowPosition] - optional clicked window position. If not given derived from position for balloons
528
- * @param {AbstractFeatureInfoView=} featureInfoView
639
+ * @param {import("./abstractFeatureInfoView.js").default=} featureInfoView
529
640
  * @returns {Promise<void>}
530
641
  */
531
642
  async selectFeature(feature, position, windowPosition, featureInfoView) {
@@ -559,6 +670,7 @@ class FeatureInfo extends Collection {
559
670
  // we need to clone the feature to avoid changing vcsLayerNameSymbol on the original feature
560
671
  const clonedFeature = feature.clone();
561
672
  clonedFeature.setId(feature.getId());
673
+ clonedFeature.set('olcs_allowPicking', true);
562
674
  this._scratchLayer.addFeatures([clonedFeature]);
563
675
  const featureId = clonedFeature.getId(); // make sure to grab ID after adding it to the layer
564
676
  this._scratchLayer.featureVisibility.highlight({
@@ -573,17 +685,17 @@ class FeatureInfo extends Collection {
573
685
  this._scratchLayer.featureVisibility.unHighlight([featureId]);
574
686
  } else if (layer.vectorClusterGroup) {
575
687
  this._ensureScratchLayer();
576
- const clone = feature.clone();
688
+ const clonedFeature = feature.clone();
577
689
  const featureId = feature.getId();
578
690
  this._scratchLayer.vectorProperties.setValuesForFeatures(
579
- layer.vectorProperties.getValuesForFeatures([clone]),
580
- [clone],
691
+ layer.vectorProperties.getValuesForFeatures([clonedFeature]),
692
+ [clonedFeature],
581
693
  );
582
- const eyeOffset = clone.get('olcs_eyeOffset') ?? [0, 0, 0];
694
+ const eyeOffset = clonedFeature.get('olcs_eyeOffset') ?? [0, 0, 0];
583
695
  eyeOffset[2] -= 10;
584
- clone.set('olcs_eyeOffset', eyeOffset);
585
- clone.setId(featureId);
586
- this._scratchLayer.addFeatures([clone]);
696
+ clonedFeature.set('olcs_eyeOffset', eyeOffset);
697
+ clonedFeature.setId(featureId);
698
+ this._scratchLayer.addFeatures([clonedFeature]);
587
699
  this._scratchLayer.featureVisibility.highlight({
588
700
  [featureId]: getHighlightStyle(
589
701
  feature,
@@ -593,7 +705,7 @@ class FeatureInfo extends Collection {
593
705
  ),
594
706
  });
595
707
  this._clearHighlightingCb = () =>
596
- this._scratchLayer.featureVisibility.unHighlight([clone]);
708
+ this._scratchLayer.featureVisibility.unHighlight([clonedFeature]);
597
709
  } else if (layer.featureVisibility) {
598
710
  const featureId = feature.getId();
599
711
  layer.featureVisibility.highlight({
@@ -608,14 +720,31 @@ class FeatureInfo extends Collection {
608
720
  layer.featureVisibility.unHighlight([featureId]);
609
721
  }
610
722
  this._windowId = usedFeatureInfoView.className; // use className for a type based position caching
723
+ const windowComponentOptions =
724
+ usedFeatureInfoView.getWindowComponentOptions(
725
+ this._app,
726
+ { feature, position, windowPosition },
727
+ layer,
728
+ );
729
+
730
+ let { props } = windowComponentOptions;
731
+ // check if Balloon should be Rendered Relative or ClampedTo Ground
732
+ if (usedFeatureInfoView instanceof BalloonFeatureInfoView) {
733
+ props = reactive(props);
734
+ if (
735
+ windowComponentOptions.props.heightReference !== HeightReference.NONE
736
+ ) {
737
+ this._destroyBalloonClampedListener = setupBalloonHeightListener(
738
+ this._app,
739
+ props,
740
+ );
741
+ }
742
+ }
611
743
  this._app.windowManager.add(
612
744
  {
613
745
  id: this._windowId,
614
- ...usedFeatureInfoView.getWindowComponentOptions(
615
- this._app,
616
- { feature, position, windowPosition },
617
- layer,
618
- ),
746
+ ...windowComponentOptions,
747
+ props,
619
748
  },
620
749
  vcsAppSymbol,
621
750
  );
@@ -645,8 +774,8 @@ class FeatureInfo extends Collection {
645
774
  const id = `cluster-at-${clusterFeature.getGeometry().getCoordinates().join('-')}`;
646
775
 
647
776
  this._ensureScratchLayer();
648
- const feature = clusterFeature.clone();
649
- feature.setId(id);
777
+ const clonedFeature = clusterFeature.clone();
778
+ clonedFeature.setId(id);
650
779
 
651
780
  clusterFeature[hidden] = true;
652
781
  clusterFeature.changed();
@@ -660,8 +789,8 @@ class FeatureInfo extends Collection {
660
789
  clusterFeature[vectorClusterGroupName],
661
790
  );
662
791
  this._scratchLayer.vectorProperties.setValuesForFeatures(
663
- clusterGroup.vectorProperties.getValuesForFeatures([feature]),
664
- [feature],
792
+ clusterGroup.vectorProperties.getValuesForFeatures([clonedFeature]),
793
+ [clonedFeature],
665
794
  );
666
795
  const clusterStyle = clusterGroup.styleFunction(clusterFeature, 1);
667
796
  const highlightStyle = getClusterHighlightStyle(
@@ -670,50 +799,20 @@ class FeatureInfo extends Collection {
670
799
  clusterStyle,
671
800
  fillColor,
672
801
  );
673
- feature.setStyle(highlightStyle);
802
+ clonedFeature.setStyle(highlightStyle);
674
803
  } else if (clusterFeature[isProvidedClusterFeature]) {
675
- feature.setStyle(
804
+ clonedFeature.setStyle(
676
805
  fromCesiumColor(Color.fromCssColorString(fillColor)).style,
677
806
  );
678
807
  }
679
808
 
680
809
  if (this._app.maps.activeMap instanceof ObliqueMap) {
681
- feature.getGeometry()[alreadyTransformedToImage] = true;
810
+ clonedFeature.getGeometry()[alreadyTransformedToImage] = true;
682
811
  }
683
- this._scratchLayer.addFeatures([feature]);
812
+ this._scratchLayer.addFeatures([clonedFeature]);
684
813
 
685
814
  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
- });
815
+ const { items, groups } = getGroupedFeatureList(this._app, features);
717
816
 
718
817
  this._clusterWindowId = id;
719
818
  this._app.windowManager.add(
@@ -722,7 +821,7 @@ class FeatureInfo extends Collection {
722
821
  component: ClusterFeatureComponent,
723
822
  props: reactive({
724
823
  items,
725
- groups: Object.values(groups),
824
+ groups,
726
825
  }),
727
826
  state: {
728
827
  headerTitle: 'featureInfo.cluster.headerTitle',
@@ -742,6 +841,7 @@ class FeatureInfo extends Collection {
742
841
  * @private
743
842
  */
744
843
  _clearInternal() {
844
+ this._destroyBalloonClampedListener();
745
845
  if (this._clearHighlightingCb) {
746
846
  this._clearHighlightingCb();
747
847
  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',
@@ -35,6 +35,7 @@
35
35
  <div class="d-flex align-center justify-space-between gc-1 w-100">
36
36
  <VcsToolButton
37
37
  v-for="{ id, action } in orderedButtons"
38
+ :data-action-name="action.name"
38
39
  :key="id"
39
40
  :tooltip="action.title"
40
41
  :icon="action.icon"
@@ -6,6 +6,7 @@
6
6
  >
7
7
  <VcsToolButton
8
8
  :key="group.action.tools[group.action.currentIndex].name"
9
+ :data-action-name="group.action.tools[group.action.currentIndex].name"
9
10
  :tooltip="group.action.tools[group.action.currentIndex].title"
10
11
  :icon="group.action.tools[group.action.currentIndex].icon"
11
12
  :active="group.action.active"
@@ -55,6 +56,7 @@
55
56
  <div class="d-flex align-center justify-space-between gc-1 w-100">
56
57
  <VcsToolButton
57
58
  v-for="(item, index) in group.action.tools"
59
+ :data-action-name="item.name"
58
60
  :key="`${item.name}-${index}`"
59
61
  :tooltip="item.title"
60
62
  :icon="item.icon"
@@ -16,6 +16,7 @@
16
16
  <div
17
17
  class="d-flex align-center justify-space-between w-100"
18
18
  v-for="group in orderedGroups"
19
+ :data-toolbox-id="group.id"
19
20
  :key="group.id"
20
21
  >
21
22
  <ToolboxActionGroup
@@ -76,7 +76,7 @@ export function isSlotPosition(windowPosition: WindowPosition): boolean;
76
76
  * headerComponent?: import("vue").Component<T, unknown, unknown>,
77
77
  * state : Partial<WindowState>,
78
78
  * position : Partial<WindowPositionOptions>,
79
- * slot: WindowSlot,
79
+ * slot: import("vue").Ref<WindowSlot>,
80
80
  * props: T,
81
81
  * provides: Record<string, unknown>,
82
82
  * zIndex: import("vue").ComputedGetter<number>
@@ -249,7 +249,7 @@ export type WindowComponent<T extends Object = Object> = {
249
249
  headerComponent?: import("vue").Component<T, unknown, unknown>;
250
250
  state: Partial<WindowState>;
251
251
  position: Partial<WindowPositionOptions>;
252
- slot: WindowSlot;
252
+ slot: import("vue").Ref<WindowSlot>;
253
253
  props: T;
254
254
  provides: Record<string, unknown>;
255
255
  zIndex: import("vue").ComputedGetter<number>;