@vcmap/ui 6.1.0-rc.6 → 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 (149) hide show
  1. package/config/base.config.json +7 -3
  2. package/config/cluster.config.json +5 -14
  3. package/config/dev.config.json +175 -56
  4. package/config/projects.config.json +2 -1
  5. package/config/splashscreen.config.json +6 -10
  6. package/config/vectorTile.config.json +42 -1
  7. package/dist/assets/{cesium-f5e8e354.js → cesium-664ad022.js} +53 -23
  8. package/dist/assets/cesium.js +1 -1
  9. package/dist/assets/{core-c134a524.js → core-841b71a4.js} +8458 -5828
  10. package/dist/assets/core.js +1 -1
  11. package/dist/assets/{ol-2752311f.js → ol-2e095c08.js} +87 -37
  12. package/dist/assets/ol.js +1 -1
  13. package/dist/assets/ui-2fd6f47d.css +1 -0
  14. package/dist/assets/{ui-83514586.js → ui-2fd6f47d.js} +21376 -20063
  15. package/dist/assets/ui.js +1 -1
  16. package/dist/assets/vue.js +1 -1
  17. package/dist/assets/{vuetify-5dbe2644.css → vuetify-4bc77ff7.css} +2 -2
  18. package/dist/assets/{vuetify-5dbe2644.js → vuetify-4bc77ff7.js} +7520 -7373
  19. package/dist/assets/vuetify.js +1 -1
  20. package/dist/index.html +1 -1
  21. package/index.d.ts +15 -5
  22. package/index.html +1 -1
  23. package/index.js +14 -5
  24. package/package.json +12 -8
  25. package/plugins/@vcmap-show-case/theming-example/src/index.js +1 -0
  26. package/plugins/@vcmap-show-case/vector-properties-example/src/LayerSettings.vue +39 -0
  27. package/plugins/@vcmap-show-case/vector-properties-example/src/VectorPropertiesExample.vue +3 -0
  28. package/plugins/@vcmap-show-case/vector-properties-example/src/lib.js +13 -0
  29. package/plugins/@vcmap-show-case/window-tester/src/WindowExample.vue +9 -0
  30. package/plugins/package.json +7 -5
  31. package/src/actions/actionHelper.d.ts +6 -0
  32. package/src/actions/actionHelper.js +22 -0
  33. package/src/actions/deepPickingAction.d.ts +23 -0
  34. package/src/actions/deepPickingAction.js +399 -0
  35. package/src/application/MapsGroupMobileMenu.vue +105 -0
  36. package/src/application/MapsGroupMobileMenu.vue.d.ts +7 -0
  37. package/src/application/VcsApp.vue +51 -24
  38. package/src/application/VcsApp.vue.d.ts +9 -2
  39. package/src/application/VcsAttributionsFooter.vue +1 -0
  40. package/src/application/VcsContainer.vue +36 -13
  41. package/src/application/VcsContainer.vue.d.ts +7 -0
  42. package/src/application/VcsMobileMenuList.vue +111 -0
  43. package/src/application/VcsMobileMenuList.vue.d.ts +2 -0
  44. package/src/application/VcsNavbar.vue +15 -3
  45. package/src/application/VcsNavbarMobile.vue +206 -0
  46. package/src/application/VcsNavbarMobile.vue.d.ts +42 -0
  47. package/src/application/VcsPositionDisplay.vue +1 -0
  48. package/src/application/VcsSplashScreen.vue +39 -7
  49. package/src/application/VcsSplashScreen.vue.d.ts +6 -0
  50. package/src/application/uiConfigHelper.d.ts +12 -0
  51. package/src/application/uiConfigHelper.js +37 -0
  52. package/src/components/buttons/VcsActionButtonList.vue +1 -0
  53. package/src/components/buttons/VcsToolButton.vue +8 -1
  54. package/src/components/buttons/VcsToolButton.vue.d.ts +1 -0
  55. package/src/components/form-inputs-controls/VcsSelect.vue +8 -6
  56. package/src/components/form-output/VcsTemplateMarkdown.vue +43 -0
  57. package/src/components/form-output/VcsTemplateMarkdown.vue.d.ts +9 -0
  58. package/src/components/icons/+all.d.ts +5 -0
  59. package/src/components/icons/+all.js +14 -0
  60. package/src/components/lists/VcsActionList.vue +1 -0
  61. package/src/components/lists/VcsGroupedList.vue +2 -1
  62. package/src/components/lists/VcsListItemComponent.vue +1 -0
  63. package/src/components/lists/VcsTreeNode.vue +11 -2
  64. package/src/components/lists/VcsTreeview.vue +40 -3
  65. package/src/components/lists/VcsTreeview.vue.d.ts +1 -0
  66. package/src/components/lists/VcsTreeviewTitle.vue +8 -1
  67. package/src/components/style/{MenuWrapper.vue → StyleMenuWrapper.vue} +2 -1
  68. package/src/components/style/VcsFillMenu.vue +4 -4
  69. package/src/components/style/VcsImageMenu.vue +4 -4
  70. package/src/components/style/VcsStrokeMenu.vue +4 -4
  71. package/src/components/style/VcsTextMenu.vue +4 -4
  72. package/src/contentTree/LayerTree.vue +8 -46
  73. package/src/contentTree/LayerTree.vue.d.ts +1 -3
  74. package/src/contentTree/contentTreeCollection.d.ts +7 -0
  75. package/src/contentTree/contentTreeCollection.js +31 -10
  76. package/src/contentTree/contentTreeItem.d.ts +4 -4
  77. package/src/contentTree/contentTreeItem.js +2 -2
  78. package/src/contentTree/flightContentTreeItem.d.ts +8 -1
  79. package/src/contentTree/flightContentTreeItem.js +26 -3
  80. package/src/contentTree/groupContentTreeItem.d.ts +21 -0
  81. package/src/contentTree/groupContentTreeItem.js +32 -2
  82. package/src/contentTree/layerContentTreeItem.d.ts +8 -1
  83. package/src/contentTree/layerContentTreeItem.js +26 -4
  84. package/src/contentTree/layerGroupContentTreeItem.d.ts +6 -0
  85. package/src/contentTree/layerGroupContentTreeItem.js +27 -3
  86. package/src/contentTree/nodeContentTreeItem.d.ts +21 -0
  87. package/src/contentTree/nodeContentTreeItem.js +31 -2
  88. package/src/contentTree/obliqueCollectionContentTreeItem.d.ts +6 -0
  89. package/src/contentTree/obliqueCollectionContentTreeItem.js +22 -2
  90. package/src/contentTree/wmsChildContentTreeItem.d.ts +56 -0
  91. package/src/contentTree/wmsChildContentTreeItem.js +159 -0
  92. package/src/contentTree/wmsGroupContentTreeItem.d.ts +171 -0
  93. package/src/contentTree/wmsGroupContentTreeItem.js +619 -0
  94. package/src/featureInfo/BalloonComponent.vue +6 -6
  95. package/src/featureInfo/ClusterFeatureComponent.vue +47 -11
  96. package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +1 -0
  97. package/src/featureInfo/MarkdownBalloonComponent.vue +3 -9
  98. package/src/featureInfo/MarkdownBalloonComponent.vue.d.ts +1 -11
  99. package/src/featureInfo/balloonFeatureInfoView.d.ts +3 -0
  100. package/src/featureInfo/balloonFeatureInfoView.js +78 -11
  101. package/src/featureInfo/balloonHelper.js +9 -13
  102. package/src/featureInfo/featureInfo.d.ts +32 -7
  103. package/src/featureInfo/featureInfo.js +192 -93
  104. package/src/featureInfo/markdownBalloonFeatureInfoView.d.ts +0 -6
  105. package/src/featureInfo/markdownBalloonFeatureInfoView.js +5 -14
  106. package/src/featureInfo/markdownFeatureInfoView.d.ts +2 -8
  107. package/src/featureInfo/markdownFeatureInfoView.js +6 -15
  108. package/src/i18n/de.d.ts +64 -50
  109. package/src/i18n/de.js +9 -0
  110. package/src/i18n/en.d.ts +64 -50
  111. package/src/i18n/en.js +9 -0
  112. package/src/legend/VcsLegend.vue +21 -2
  113. package/src/legend/VcsLegend.vue.d.ts +1 -0
  114. package/src/legend/legendHelper.d.ts +0 -13
  115. package/src/legend/legendHelper.js +3 -27
  116. package/src/manager/navbarManager.d.ts +14 -1
  117. package/src/manager/navbarManager.js +22 -2
  118. package/src/manager/toolbox/GroupToolboxComponent.vue +17 -3
  119. package/src/manager/toolbox/GroupToolboxComponent.vue.d.ts +1 -0
  120. package/src/manager/toolbox/SelectToolboxComponent.vue +17 -3
  121. package/src/manager/toolbox/SelectToolboxComponent.vue.d.ts +1 -0
  122. package/src/manager/toolbox/ToolboxManagerComponent.vue +45 -14
  123. package/src/manager/toolbox/ToolboxManagerComponent.vue.d.ts +9 -0
  124. package/src/manager/toolbox/toolboxManager.d.ts +2 -1
  125. package/src/manager/toolbox/toolboxManager.js +13 -1
  126. package/src/manager/window/WindowComponent.vue +3 -2
  127. package/src/manager/window/WindowComponentHeader.vue +9 -1
  128. package/src/manager/window/WindowComponentHeader.vue.d.ts +1 -0
  129. package/src/manager/window/WindowManager.vue +175 -30
  130. package/src/manager/window/WindowManager.vue.d.ts +5 -0
  131. package/src/manager/window/windowManager.d.ts +2 -2
  132. package/src/manager/window/windowManager.js +12 -10
  133. package/src/navigation/MapNavigation.vue +29 -19
  134. package/src/navigation/MapNavigation.vue.d.ts +1 -0
  135. package/src/notifier/NotifierComponent.vue +1 -0
  136. package/src/search/ResultsComponent.vue +44 -17
  137. package/src/search/ResultsComponent.vue.d.ts +11 -1
  138. package/src/search/SearchComponent.vue +60 -9
  139. package/src/search/SearchComponent.vue.d.ts +2 -0
  140. package/src/search/search.js +3 -16
  141. package/src/state.d.ts +2 -1
  142. package/src/state.js +2 -1
  143. package/src/uiConfig.d.ts +9 -0
  144. package/src/uiConfig.js +1 -0
  145. package/src/vuePlugins/vuetify.d.ts +4 -0
  146. package/src/vuePlugins/vuetify.js +49 -3
  147. package/dist/assets/ui-83514586.css +0 -1
  148. /package/dist/assets/{vue-f8b1b5f8.js → vue-71fd14e8.js} +0 -0
  149. /package/src/components/style/{MenuWrapper.vue.d.ts → StyleMenuWrapper.vue.d.ts} +0 -0
@@ -0,0 +1,399 @@
1
+ import {
2
+ cartesianToMercator,
3
+ FeatureProviderInteraction,
4
+ getFeatureFromPickObject,
5
+ isProvidedClusterFeature,
6
+ isProvidedFeature,
7
+ markVolatile,
8
+ maxZIndex,
9
+ mercatorProjection,
10
+ mercatorToCartesian,
11
+ moduleIdSymbol,
12
+ originalFeatureSymbol,
13
+ vcsLayerName,
14
+ vectorClusterGroupName,
15
+ VectorLayer,
16
+ VectorStyleItem,
17
+ volatileModuleId,
18
+ } from '@vcmap/core';
19
+ import { Feature } from 'ol';
20
+ import { Point, LineString } from 'ol/geom.js';
21
+ import { Icon } from 'ol/style.js';
22
+ import { Cartesian3, Ray } from '@vcmap-cesium/engine';
23
+ import { watch } from 'vue';
24
+ import { getColorByKey } from '../vuePlugins/vuetify.js';
25
+ import ClusterFeatureComponent from '../featureInfo/ClusterFeatureComponent.vue';
26
+ import { WindowSlot } from '../manager/window/windowManager.js';
27
+ import { vcsAppSymbol } from '../pluginHelper.js';
28
+ import {
29
+ featureInfoViewSymbol,
30
+ getFeatureInfoViewForFeature,
31
+ getGroupedFeatureList,
32
+ } from '../featureInfo/featureInfo.js';
33
+ import { getColoredMapIcon } from '../components/icons/+all.js';
34
+
35
+ const scratchCartesian = new Cartesian3();
36
+ const pickingZOffset = 10.0;
37
+ const iconScale = 1.5;
38
+
39
+ export const deepPickingWindowId = 'deep-picking-window';
40
+
41
+ /**
42
+ * @param {import("@vcmap/ui").VcsUiApp} app
43
+ * @returns {{ layer: import("@vcmap/core").VectorLayer, destroy: () => void }}
44
+ */
45
+ export function setupDeepPickingLayer(app) {
46
+ const layer = new VectorLayer({
47
+ zIndex: maxZIndex,
48
+ projection: mercatorProjection.toJSON(),
49
+ vectorProperties: {
50
+ altitudeMode: 'absolute',
51
+ eyeOffset: [0, 0, -200],
52
+ },
53
+ allowPicking: false,
54
+ });
55
+ markVolatile(layer);
56
+ app.layers.add(layer);
57
+ layer.activate();
58
+
59
+ const style = new VectorStyleItem({
60
+ image: {
61
+ ...getColoredMapIcon(getColorByKey(app, 'primary')),
62
+ scale: iconScale,
63
+ },
64
+ fill: {
65
+ color: 'rgba(237, 237, 237, 0.1)',
66
+ },
67
+ stroke: {
68
+ color: getColorByKey(app, 'primary'),
69
+ width: 5,
70
+ },
71
+ });
72
+ layer.setStyle(style);
73
+
74
+ function setIconColor() {
75
+ const color = getColorByKey(app, 'primary');
76
+ style.stroke?.setColor(color);
77
+ style.image = new Icon({ ...getColoredMapIcon(color), scale: iconScale });
78
+ layer.forceRedraw();
79
+ }
80
+
81
+ const themChangedListener = app.themeChanged.addEventListener(setIconColor);
82
+
83
+ const destroy = () => {
84
+ layer.deactivate();
85
+ app.layers.remove(layer);
86
+ layer.destroy();
87
+ themChangedListener();
88
+ };
89
+
90
+ return { layer, destroy };
91
+ }
92
+
93
+ /**
94
+ * Retrieves features from an OpenLayers map at a given pixel.
95
+ * @param {import("ol/Map.js").OLMap} map
96
+ * @param {[number, number]} pixel
97
+ * @param {number} hitTolerance
98
+ * @param {number} drill
99
+ * @returns {import("ol").Feature[]}
100
+ */
101
+ function getFeaturesFromOlMap(map, pixel, hitTolerance, drill) {
102
+ const features = [];
103
+ let i = 0;
104
+ map.forEachFeatureAtPixel(
105
+ pixel,
106
+ (feat) => {
107
+ if (
108
+ feat &&
109
+ (feat.get('olcs_allowPicking') == null ||
110
+ feat.get('olcs_allowPicking') === true)
111
+ ) {
112
+ const feature = feat[originalFeatureSymbol] || feat;
113
+ if (!feature[vectorClusterGroupName]) {
114
+ features.push(feature);
115
+ }
116
+ }
117
+ i += 1;
118
+ return i >= drill;
119
+ },
120
+ { hitTolerance },
121
+ );
122
+
123
+ return features;
124
+ }
125
+
126
+ /**
127
+ * Retrieves features from a Cesium scene at a given window position.
128
+ * @param {import("@vcmap-cesium/engine").Scene} scene
129
+ * @param {import("@vcmap-cesium/engine").Ray} ray
130
+ * @param {number} hitTolerance
131
+ * @param {number} drill
132
+ * @returns {Promise<{ features: import("@vcmap/core").EventFeature[], minZ: number }>}
133
+ */
134
+ async function getFeaturesFromScene(scene, ray, hitTolerance, drill) {
135
+ const { depthTestAgainstTerrain } = scene.globe;
136
+ scene.globe.depthTestAgainstTerrain = false;
137
+
138
+ let minZ = 0;
139
+ const objects = await scene.drillPickFromRay(
140
+ ray,
141
+ drill,
142
+ undefined,
143
+ hitTolerance,
144
+ );
145
+
146
+ scene.globe.depthTestAgainstTerrain = depthTestAgainstTerrain;
147
+
148
+ const features = objects
149
+ .map(({ object, position }) => {
150
+ let feature;
151
+ if (object) {
152
+ if (position) {
153
+ const z = cartesianToMercator(position)[2];
154
+ minZ = Math.min(minZ, z);
155
+ }
156
+ feature = getFeatureFromPickObject(object);
157
+ if (feature?.[vectorClusterGroupName]) {
158
+ const clusterFeatures = feature.get('features');
159
+ return [...clusterFeatures];
160
+ }
161
+ }
162
+ return feature;
163
+ })
164
+ .filter((f, i, a) => !!f && a.indexOf(f) === i);
165
+ return { features, minZ };
166
+ }
167
+
168
+ /**
169
+ * @param {import("@vcmap/core").InteractionEvent} event
170
+ * @param {number} [hitTolerance=10]
171
+ * @param {number} [drillLimit]
172
+ * @returns {Promise<{ features: import("@vcmap/core").EventFeature[], minZ: number }>}
173
+ */
174
+ async function getDeepPickingFeatures(
175
+ event,
176
+ hitTolerance = 10,
177
+ drillLimit = undefined,
178
+ ) {
179
+ let features = [];
180
+ let minZ = 0;
181
+ if (
182
+ event.map.className === 'OpenlayersMap' ||
183
+ event.map.className === 'ObliqueMap'
184
+ ) {
185
+ features = getFeaturesFromOlMap(
186
+ event.map.olMap,
187
+ [event.windowPosition.x, event.windowPosition.y],
188
+ hitTolerance,
189
+ drillLimit,
190
+ );
191
+ } else if (event.map.className === 'CesiumMap') {
192
+ const cesiumMap = event.map;
193
+ const scene = cesiumMap.getScene();
194
+
195
+ if (!scene) {
196
+ return features;
197
+ }
198
+
199
+ const [x, y, z] = event.position;
200
+ const origin = mercatorToCartesian([
201
+ x,
202
+ y,
203
+ Number.isNaN(z) ? pickingZOffset : z + pickingZOffset,
204
+ ]);
205
+ const direction = Cartesian3.normalize(
206
+ Cartesian3.negate(origin, scratchCartesian),
207
+ scratchCartesian,
208
+ );
209
+ const ray = new Ray(origin, direction);
210
+
211
+ ({ features, minZ } = await getFeaturesFromScene(
212
+ scene,
213
+ ray,
214
+ hitTolerance,
215
+ drillLimit,
216
+ ));
217
+ }
218
+
219
+ if (
220
+ event.feature &&
221
+ !event.feature[isProvidedFeature] && // provided features will be provided again.
222
+ !features.includes(event.feature)
223
+ ) {
224
+ features.unshift(event.feature);
225
+ }
226
+
227
+ return { features, minZ };
228
+ }
229
+
230
+ /**
231
+ * @param {import("@vcmap/core").AbstractInteraction} interaction
232
+ * @param {import("@vcmap/core").InteractionEvent} event
233
+ * @returns {Promise<import("@vcmap/core").EventFeature[]>}
234
+ */
235
+ async function getInteractionFeatures(interaction, event) {
236
+ const pipedEvent = await interaction.pipe({
237
+ ...event,
238
+ feature: undefined,
239
+ });
240
+ const { feature } = pipedEvent;
241
+ if (feature) {
242
+ if (feature[isProvidedClusterFeature]) {
243
+ return feature.get('features');
244
+ }
245
+ return [feature];
246
+ }
247
+ return [];
248
+ }
249
+
250
+ /**
251
+ * @returns {{ collectFeatures: (event: import("@vcmap/core").InteractionEvent) => Promise<{ features: import("@vcmap/core").EventFeature[], minZ: number }>, destroy: () => void}}
252
+ */
253
+ function createCollectFeatures() {
254
+ const featureProviderInteraction = new FeatureProviderInteraction();
255
+ return {
256
+ async collectFeatures(event) {
257
+ const { features: deepPickingFeatures, minZ } =
258
+ await getDeepPickingFeatures(event);
259
+ return {
260
+ features: [
261
+ ...deepPickingFeatures,
262
+ ...(await getInteractionFeatures(featureProviderInteraction, event)),
263
+ ],
264
+ minZ,
265
+ };
266
+ },
267
+ destroy() {
268
+ featureProviderInteraction.destroy();
269
+ },
270
+ };
271
+ }
272
+
273
+ /**
274
+ * @param {import("../vcsUiApp.js").default} app
275
+ * @param {import("ol/Feature").default} f
276
+ * @returns {boolean}
277
+ */
278
+ function featurePredicate(app, f) {
279
+ if (f[featureInfoViewSymbol]) {
280
+ return true;
281
+ }
282
+
283
+ const l = app.layers.getByKey(f[vcsLayerName]);
284
+ if (l?.[moduleIdSymbol] === volatileModuleId) {
285
+ return !!getFeatureInfoViewForFeature(app, f);
286
+ }
287
+
288
+ return !!l;
289
+ }
290
+
291
+ /**
292
+ * @param {import("../vcsUiApp.js").default} app
293
+ * @param {import("@vcmap/core").VectorLayer} layer
294
+ * @param {(event: import("@vcmap/core").InteractionEvent) => Promise<import("@vcmap/core").EventFeature[]>} collectFeatures
295
+ * @param {import("@vcmap/core").InteractionEvent} event
296
+ * @returns {import("./actionHelper.js").VcsAction}
297
+ */
298
+ export function createDeepPickingAction(app, layer, collectFeatures, event) {
299
+ return {
300
+ name: 'featureInfo.deepPicking.title',
301
+ icon: '$vcsInfo',
302
+ async callback() {
303
+ const { features, minZ } = await collectFeatures(event);
304
+ const { items, groups } = getGroupedFeatureList(
305
+ app,
306
+ features.filter((f) => featurePredicate(app, f)),
307
+ event.position,
308
+ );
309
+
310
+ if (app.windowManager.has(deepPickingWindowId)) {
311
+ app.windowManager.remove(deepPickingWindowId);
312
+ }
313
+
314
+ app.windowManager.add(
315
+ {
316
+ id: deepPickingWindowId,
317
+ component: ClusterFeatureComponent,
318
+ props: {
319
+ items,
320
+ groups,
321
+ },
322
+ state: {
323
+ headerTitle: 'featureInfo.deepPicking.headerTitle',
324
+ headerIcon: '$vcsInfo',
325
+ },
326
+ slot: WindowSlot.DYNAMIC_LEFT,
327
+ },
328
+ vcsAppSymbol,
329
+ );
330
+
331
+ const windowListener = app.windowManager.removed.addEventListener(
332
+ ({ id: windowId }) => {
333
+ if (windowId === deepPickingWindowId) {
334
+ layer.removeAllFeatures();
335
+ windowListener();
336
+ }
337
+ },
338
+ );
339
+
340
+ const [x, y, z] = event.position;
341
+ const coordinate = [
342
+ x,
343
+ y,
344
+ Number.isNaN(z) ? pickingZOffset : z + pickingZOffset,
345
+ ];
346
+ const pickFeature = new Feature({
347
+ geometry: new Point(coordinate),
348
+ });
349
+ const rayFeature = new Feature({
350
+ geometry: new LineString([coordinate, [x, y, minZ]]),
351
+ });
352
+ layer.addFeatures([pickFeature, rayFeature]);
353
+ },
354
+ };
355
+ }
356
+
357
+ /**
358
+ * This adds deep picking action to the context menu, if not disabled in uiConfig
359
+ * @param {import("../vcsUiApp.js").default} app
360
+ * @returns {() => void}
361
+ */
362
+ export function setupDeepPicking(app) {
363
+ const { layer, destroy: destroyLayer } = setupDeepPickingLayer(app);
364
+ const { collectFeatures, destroy: destroyCollectFeatures } =
365
+ createCollectFeatures();
366
+
367
+ const handler = async (event) => {
368
+ if (event.windowPosition) {
369
+ return [createDeepPickingAction(app, layer, collectFeatures, event)];
370
+ }
371
+ return [];
372
+ };
373
+
374
+ if (app.uiConfig.enableDeepPicking !== false) {
375
+ app.contextMenuManager.addEventHandler(handler, vcsAppSymbol);
376
+ }
377
+
378
+ const stopWatching = watch(
379
+ () => app.uiConfig.config.enableDeepPicking,
380
+ (value, oldValue) => {
381
+ if (value !== false) {
382
+ if (!(oldValue !== false)) {
383
+ app.contextMenuManager.addEventHandler(handler, vcsAppSymbol);
384
+ }
385
+ } else {
386
+ app.contextMenuManager.removeHandler(handler);
387
+ }
388
+ },
389
+ );
390
+
391
+ return () => {
392
+ stopWatching();
393
+ destroyLayer();
394
+ destroyCollectFeatures();
395
+ layer.deactivate();
396
+ layer.destroy();
397
+ app.layers.remove(layer);
398
+ };
399
+ }
@@ -0,0 +1,105 @@
1
+ <template>
2
+ <div v-if="mapActions.length > 0" class="maps-group-mobile-menu">
3
+ <v-menu v-model="open" location="center" z-index="99">
4
+ <template #activator="{ props }">
5
+ <VcsToolButton
6
+ class="vcs-toolbox-toggle-button pl-4"
7
+ width="50"
8
+ :icon="activeIcon"
9
+ v-bind="props"
10
+ >
11
+ <v-icon>{{ open ? 'mdi-chevron-up' : 'mdi-chevron-down' }}</v-icon>
12
+ </VcsToolButton>
13
+ </template>
14
+
15
+ <v-toolbar
16
+ class="vcs-toolbox-toolbar--secondary mx-auto bottom-align rounded-t elevation-4 opacity-80 px-1"
17
+ :height="toolboxHeight"
18
+ >
19
+ <v-toolbar-items class="w-100">
20
+ <div class="d-flex align-center justify-space-between gc-1 w-100">
21
+ <VcsToolButton
22
+ v-for="action in mapActions"
23
+ :key="action.id"
24
+ :tooltip="action.title"
25
+ :icon="action.icon"
26
+ :disabled="action.disabled"
27
+ :active="action.active"
28
+ @click.stop="
29
+ () => {
30
+ $emit('click', $event);
31
+ open = false;
32
+ action.callback($event);
33
+ }
34
+ "
35
+ v-bind="{ ...$attrs }"
36
+ />
37
+ </div>
38
+ </v-toolbar-items>
39
+ </v-toolbar>
40
+ </v-menu>
41
+ </div>
42
+ </template>
43
+ <style lang="scss" scoped>
44
+ .bottom-align {
45
+ bottom: calc(var(--v-vcs-font-size) * 3 - 2px) !important;
46
+ }
47
+ </style>
48
+ <script>
49
+ import { computed, ref, inject } from 'vue';
50
+ import { VMenu, VIcon, VToolbar, VToolbarItems } from 'vuetify/components';
51
+ import VcsToolButton from '../components/buttons/VcsToolButton.vue';
52
+ import { useFontSize } from '../vuePlugins/vuetify.js';
53
+ import {
54
+ ButtonLocation,
55
+ deviceSymbol,
56
+ getActionsByLocation,
57
+ } from '../manager/navbarManager.js';
58
+
59
+ export default {
60
+ name: 'MapsGroupMobileMenu',
61
+ components: {
62
+ VcsToolButton,
63
+ VMenu,
64
+ VIcon,
65
+ VToolbar,
66
+ VToolbarItems,
67
+ },
68
+ setup() {
69
+ const app = inject('vcsApp');
70
+ const open = ref(false);
71
+
72
+ const mobileButtonComponents = computed(() =>
73
+ app.navbarManager.componentIds
74
+ .map((id) => app.navbarManager.get(id))
75
+ .filter((buttonComponent) => {
76
+ return buttonComponent[deviceSymbol].mobile;
77
+ }),
78
+ );
79
+
80
+ const mapActions = computed(() =>
81
+ getActionsByLocation(
82
+ mobileButtonComponents.value,
83
+ ButtonLocation.MAP,
84
+ [...app.plugins].map((p) => p.name),
85
+ ),
86
+ );
87
+
88
+ const activeIcon = computed(
89
+ () => mapActions.value.find((a) => a.active)?.icon,
90
+ );
91
+
92
+ const fontSize = useFontSize();
93
+ const toolboxHeight = computed(() => {
94
+ return fontSize.value * 3 + 5;
95
+ });
96
+
97
+ return {
98
+ open,
99
+ activeIcon,
100
+ toolboxHeight,
101
+ mapActions,
102
+ };
103
+ },
104
+ };
105
+ </script>
@@ -0,0 +1,7 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {
2
+ open: import("vue").Ref<boolean>;
3
+ activeIcon: import("vue").ComputedRef<string | undefined>;
4
+ toolboxHeight: import("vue").ComputedRef<number>;
5
+ mapActions: import("vue").ComputedRef<import("../actions/actionHelper.js", { with: { "resolution-mode": "import" } }).VcsAction[]>;
6
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
7
+ export default _default;