@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
@@ -1,10 +1,5 @@
1
1
  <template>
2
- <div
3
- :class="{
4
- 'win-container-mobile': addMobileClass,
5
- }"
6
- class="window-manager"
7
- >
2
+ <div class="window-manager" :class="{ oblique: isOblique, mobile: xs }">
8
3
  <WindowComponent
9
4
  v-for="id in componentIds"
10
5
  :key="id"
@@ -13,6 +8,9 @@
13
8
  :z-index="getComponent(id).zIndex"
14
9
  @moved="move(id, $event)"
15
10
  @mousedown="bringWindowToTop(id)"
11
+ @touchstart="onTouchStart($event)"
12
+ @touchmove="onTouchMove($event)"
13
+ @touchend="onTouchEnd($event, id)"
16
14
  :style="getStyles(id).value"
17
15
  :class="getState(id).classes"
18
16
  :is-on-top="isOnTop(id)"
@@ -39,30 +37,50 @@
39
37
  </template>
40
38
 
41
39
  <style scoped lang="scss">
42
- .win-container-mobile {
40
+ .mobile > div:not(#window-component--searchId) {
43
41
  position: fixed;
44
- bottom: 56px;
45
42
  left: 0;
46
43
  right: 0;
47
44
  z-index: 2;
48
45
  display: contents;
46
+ width: 100% !important;
47
+ max-width: 100% !important;
48
+ inset: unset !important;
49
+ border-radius: 0 !important;
50
+ overflow: auto;
51
+ bottom: 0 !important;
52
+ max-height: 50% !important;
49
53
  }
50
- .win-container-mobile > {
51
- div {
52
- width: 100% !important;
53
- max-width: 100% !important;
54
- inset: unset !important;
55
- border-radius: 0 !important;
56
- overflow: auto;
57
- bottom: 0 !important;
58
- max-height: 50% !important;
54
+ .mobile > div {
55
+ transition: transform 0.4s ease;
56
+ }
57
+
58
+ .mobile > #window-component--searchId {
59
+ position: fixed !important;
60
+ top: calc(var(--v-vcs-font-size) * 5 + 28px) !important;
61
+ left: 5px !important;
62
+ right: calc(var(--v-vcs-font-size) * 5 + 2px) !important;
63
+ z-index: 2;
64
+ border-radius: 4px !important;
65
+ width: inherit !important;
66
+ padding-right: 1px !important;
67
+ .py-1 {
68
+ padding: 0px !important;
59
69
  }
60
70
  }
71
+ .mobile > #window-component--searchId > div > div {
72
+ border-radius: 4px !important;
73
+ }
74
+
75
+ .oblique > #window-component--searchId {
76
+ right: calc(var(--v-vcs-font-size) * 6.25 + 2px) !important;
77
+ }
61
78
  </style>
62
79
 
63
80
  <script>
64
- import { computed, inject, onUnmounted, ref } from 'vue';
81
+ import { computed, inject, onUnmounted, ref, watch } from 'vue';
65
82
  import { useDisplay } from 'vuetify';
83
+ import { ObliqueMap } from '@vcmap/core';
66
84
  import WindowComponent from './WindowComponent.vue';
67
85
  import WindowComponentHeader from './WindowComponentHeader.vue';
68
86
  import BalloonComponent from '../../featureInfo/BalloonComponent.vue';
@@ -71,6 +89,8 @@
71
89
  getTargetSize,
72
90
  moveWindow,
73
91
  } from './windowHelper.js';
92
+ import { mobileMenuListId } from '../../application/VcsNavbarMobile.vue';
93
+ import { useFontSize } from '../../vuePlugins/vuetify.js';
74
94
 
75
95
  /**
76
96
  * @description WindowManager rendering all registered WindowComponents
@@ -81,9 +101,14 @@
81
101
  setup() {
82
102
  const app = inject('vcsApp');
83
103
  /** @type {WindowManager} */
84
- const { windowManager } = app;
104
+ const { windowManager, toolboxManager } = app;
85
105
  const { componentIds } = windowManager;
86
106
  const targetSize = ref(null);
107
+ const touchStartY = ref(0);
108
+ const touchCurrentY = ref(0);
109
+ const isTouching = ref(false);
110
+ const fontSize = useFontSize();
111
+ const { sm } = useDisplay();
87
112
  /**
88
113
  * @param {string} id
89
114
  * @returns {WindowState}
@@ -128,14 +153,28 @@
128
153
  // do not clip balloons to target
129
154
  return windowComponent?.position;
130
155
  }
156
+ // reduce target size for Tablet View to compensate for the toolbar not overlapping
157
+ const size = structuredClone(targetSize.value);
158
+ if (toolboxManager.open.value && sm.value && size) {
159
+ size.height -= fontSize.value * 3 + 6;
160
+ }
161
+
131
162
  return getPositionAppliedOnTarget(
132
163
  windowComponent?.position,
133
- targetSize.value,
164
+ size,
134
165
  getPosition(parentComponent),
135
166
  );
136
167
  };
137
168
  const display = useDisplay();
138
169
 
170
+ const addMobileClass = computed(() => {
171
+ return display.xs.value && componentIds.length > 0;
172
+ });
173
+
174
+ const addTabletClass = computed(() => {
175
+ return display.sm.value && componentIds.length > 0;
176
+ });
177
+
139
178
  /**
140
179
  * @param {string} id
141
180
  * @returns {import("vue").ComputedRef<Object>}
@@ -143,14 +182,22 @@
143
182
  const getStyles = (id) =>
144
183
  computed(() => {
145
184
  const windowComponent = windowManager.get(id);
146
- const zIndexOffset = Number(display.sm.value); // add z-Index Offset for Tablet View to keep the windows above the detached Icon
185
+ const zIndexOffset =
186
+ Number(display.sm.value) || Number(display.xs.value); // add z-Index Offset for Tablet View to keep the windows above the detached Icon
147
187
  return {
148
- zIndex: windowComponent.zIndex.value + zIndexOffset,
188
+ zIndex: `${windowComponent.zIndex.value + zIndexOffset} !important`,
149
189
  ...getPosition(windowComponent),
150
190
  ...(windowComponent?.state?.styles || {}),
151
191
  };
152
192
  });
153
193
 
194
+ const isOblique = ref(false);
195
+ // fix search width to oblique map
196
+ const mobileSearchObliqueListener =
197
+ app.maps.mapActivated.addEventListener((map) => {
198
+ isOblique.value = map instanceof ObliqueMap;
199
+ });
200
+
154
201
  /**
155
202
  * @param {string} id
156
203
  */
@@ -169,14 +216,6 @@
169
216
  moveWindow(id, translation, windowManager, targetSize.value, position);
170
217
  };
171
218
 
172
- const addMobileClass = computed(() => {
173
- return display.xs.value && componentIds.length > 0;
174
- });
175
-
176
- const addTabletClass = computed(() => {
177
- return display.sm.value && componentIds.length > 0;
178
- });
179
-
180
219
  const setTargetSize = () => {
181
220
  targetSize.value = getTargetSize(app.maps.target);
182
221
  };
@@ -184,11 +223,112 @@
184
223
  const setTargetDestroy =
185
224
  app.maps.mapActivated.addEventListener(setTargetSize);
186
225
 
226
+ let exclusiveWindowListener;
227
+
228
+ /**
229
+ * Sets up an exclusive window listener for mobile view.
230
+ * When a new window is added, it removes all other windows except the search window.
231
+ * The search window is placed at the top of the page and allows opening of one other window, e.g. for displaying feature information.
232
+ */
233
+ function setupExclusiveWindowListener() {
234
+ if (display.xs.value) {
235
+ exclusiveWindowListener = app.windowManager.added.addEventListener(
236
+ (e) => {
237
+ componentIds
238
+ .filter((id) => id !== e.id)
239
+ .forEach((id) => {
240
+ if (id !== 'searchId') {
241
+ app.windowManager.remove(id);
242
+ } else if (
243
+ id === 'searchId' &&
244
+ componentIds.includes('Content')
245
+ ) {
246
+ app.windowManager.remove('searchId');
247
+ }
248
+ });
249
+ },
250
+ );
251
+ } else {
252
+ exclusiveWindowListener?.();
253
+ }
254
+ }
255
+
256
+ setupExclusiveWindowListener();
257
+
258
+ watch(display.xs, () => {
259
+ setupExclusiveWindowListener();
260
+ if (componentIds.includes(mobileMenuListId)) {
261
+ windowManager.remove(mobileMenuListId);
262
+ }
263
+ });
264
+
187
265
  onUnmounted(() => {
188
266
  window.removeEventListener('resize', setTargetSize);
267
+ exclusiveWindowListener?.();
189
268
  setTargetDestroy();
269
+ mobileSearchObliqueListener();
190
270
  });
191
271
 
272
+ /**
273
+ * Handles the touch start event for mobile view.
274
+ * Initializes the touch start position and sets the isTouching flag.
275
+ * Only starts the drag if the touch starts within the first 50 pixels of the window.
276
+ * @param {TouchEvent} event - The touch start event.
277
+ */
278
+ const onTouchStart = (event) => {
279
+ if (!addMobileClass.value) return; // Only on mobile view
280
+ const windowElement = event.currentTarget;
281
+ // Get the Y-coordinate of the drag start relative to the window's top
282
+ const touchStartYRelativeToWindow =
283
+ event.touches[0].clientY - windowElement.getBoundingClientRect().top;
284
+ // Only start drag if the starting position is within the first 50 pixels of the window
285
+ if (touchStartYRelativeToWindow > 50) return;
286
+ touchStartY.value = event.touches[0].clientY;
287
+ touchCurrentY.value = touchStartY.value;
288
+ isTouching.value = true;
289
+ };
290
+
291
+ /**
292
+ * Handles the touch move event for mobile view.
293
+ * Adjusts the window position during drag based on the touch movement.
294
+ * @param {TouchEvent} event - The touch move event.
295
+ */
296
+ const onTouchMove = (event) => {
297
+ if (!isTouching.value) return;
298
+ touchCurrentY.value = event.touches[0].clientY;
299
+
300
+ // Adjust the window position during drag
301
+ const deltaY = touchCurrentY.value - touchStartY.value;
302
+ const windowElement = event.currentTarget;
303
+ if (windowElement) {
304
+ windowElement.style.transform = `translateY(${Math.max(0, deltaY)}px)`;
305
+ }
306
+ };
307
+
308
+ /**
309
+ * Handles the touch end event for mobile view.
310
+ * Resets the isTouching flag and checks if the window should be closed based on the drag distance.
311
+ * @param {TouchEvent} event - The touch end event.
312
+ * @param {string} id - The ID of the window component.
313
+ */
314
+ const onTouchEnd = (event, id) => {
315
+ if (!isTouching.value) return;
316
+ isTouching.value = false;
317
+
318
+ const deltaY = touchCurrentY.value - touchStartY.value;
319
+ const windowElement = event.currentTarget;
320
+
321
+ if (windowElement) {
322
+ // reset the transform style so it opens fully again if the window is not fully closed
323
+ windowElement.style.transform = '';
324
+
325
+ // Close if dragged down far enough 1/3 of the window height
326
+ if (deltaY > windowElement.offsetHeight / 3) {
327
+ windowManager.remove(id);
328
+ }
329
+ }
330
+ };
331
+
192
332
  return {
193
333
  componentIds,
194
334
  getComponent: (id) => windowManager.get(id).component,
@@ -209,6 +349,11 @@
209
349
  move,
210
350
  addMobileClass,
211
351
  addTabletClass,
352
+ onTouchStart,
353
+ onTouchMove,
354
+ onTouchEnd,
355
+ isOblique,
356
+ xs: display.xs,
212
357
  };
213
358
  },
214
359
  };
@@ -16,5 +16,10 @@ declare const _default: import("vue").DefineComponent<{}, {
16
16
  }) => void;
17
17
  addMobileClass: import("vue").ComputedRef<boolean>;
18
18
  addTabletClass: import("vue").ComputedRef<boolean>;
19
+ onTouchStart: (event: TouchEvent) => void;
20
+ onTouchMove: (event: TouchEvent) => void;
21
+ onTouchEnd: (event: TouchEvent, id: string) => void;
22
+ isOblique: import("vue").Ref<boolean>;
23
+ xs: import("vue").Ref<boolean>;
19
24
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
20
25
  export default _default;
@@ -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>;
@@ -170,7 +170,7 @@ export function isSlotPosition(windowPosition) {
170
170
  * headerComponent?: import("vue").Component<T, unknown, unknown>,
171
171
  * state : Partial<WindowState>,
172
172
  * position : Partial<WindowPositionOptions>,
173
- * slot: WindowSlot,
173
+ * slot: import("vue").Ref<WindowSlot>,
174
174
  * props: T,
175
175
  * provides: Record<string, unknown>,
176
176
  * zIndex: import("vue").ComputedGetter<number>
@@ -545,15 +545,17 @@ class WindowManager {
545
545
  * @private
546
546
  */
547
547
  _cachePosition(windowComponent) {
548
- const initialWindowPosition = windowPositionFromOptions(
549
- windowComponent.initialPositionOptions,
550
- );
551
- if (
552
- !compareWindowPositions(initialWindowPosition, windowComponent.position)
553
- ) {
554
- this._windowPositionsCache.set(windowComponent.id, {
555
- ...windowComponent.position,
556
- });
548
+ if (windowComponent.slot.value === WindowSlot.DETACHED) {
549
+ const initialWindowPosition = windowPositionFromOptions(
550
+ windowComponent.initialPositionOptions,
551
+ );
552
+ if (
553
+ !compareWindowPositions(initialWindowPosition, windowComponent.position)
554
+ ) {
555
+ this._windowPositionsCache.set(windowComponent.id, {
556
+ ...windowComponent.position,
557
+ });
558
+ }
557
559
  }
558
560
  }
559
561
 
@@ -1,6 +1,8 @@
1
1
  <template>
2
2
  <v-container
3
- :class="xs ? 'nav-container mobile' : 'nav-container'"
3
+ :class="
4
+ xs || mobileLandscape ? 'nav-container mobile no-zoom ' : 'nav-container'
5
+ "
4
6
  class="map-navigation"
5
7
  >
6
8
  <v-row>
@@ -25,7 +27,7 @@
25
27
  ></OrientationToolsButton>
26
28
  </v-row>
27
29
  </template>
28
- <template v-if="smAndUp">
30
+ <template v-if="smAndUp && !mobileLandscape">
29
31
  <v-row justify="center">
30
32
  <VcsZoomButton
31
33
  @zoom-out="zoomOut()"
@@ -33,7 +35,7 @@
33
35
  :disabled="movementApiCallsDisabled"
34
36
  />
35
37
  </v-row>
36
- <v-row justify="center" v-if="is3D && smAndUp">
38
+ <v-row justify="center" v-if="is3D">
37
39
  <TiltSlider v-model="tilt" :disabled="movementApiCallsDisabled" />
38
40
  </v-row>
39
41
  <v-row v-if="!hideRotationButton && is3D" justify="center">
@@ -45,15 +47,17 @@
45
47
  :disabled="rotationAction.disabled"
46
48
  />
47
49
  </v-row>
48
- <v-row justify="center">
49
- <OrientationToolsButton
50
- v-if="homeAction.icon"
51
- :icon="homeAction.icon"
52
- :tooltip="homeAction.title"
53
- @click.stop="homeAction.callback($event)"
54
- :disabled="movementApiCallsDisabled"
55
- />
56
- </v-row>
50
+ </template>
51
+ <v-row justify="center">
52
+ <OrientationToolsButton
53
+ v-if="homeAction.icon"
54
+ :icon="homeAction.icon"
55
+ :tooltip="homeAction.title"
56
+ @click.stop="homeAction.callback($event)"
57
+ :disabled="movementApiCallsDisabled"
58
+ />
59
+ </v-row>
60
+ <template v-if="!mobileLandscape">
57
61
  <v-row justify="center">
58
62
  <OrientationToolsButton
59
63
  v-if="showOverviewButton"
@@ -90,6 +94,7 @@
90
94
  import TiltSlider from './TiltSlider.vue';
91
95
  import ObliqueRotation from './ObliqueRotation.vue';
92
96
  import OrientationToolsButton from './OrientationToolsButton.vue';
97
+ import { isMobileLandscape } from '../vuePlugins/vuetify.js';
93
98
 
94
99
  /**
95
100
  * @description Creates a go-to viewpoint action from a startingViewpointName defined in a module. If no startingViewpointName is defined, uses default map view as fallback.
@@ -183,6 +188,8 @@
183
188
  options.keyEvents === true &&
184
189
  options.apiCalls === true &&
185
190
  options.pointerEvents === true;
191
+
192
+ stopRotation = null;
186
193
  });
187
194
  return {
188
195
  action,
@@ -280,6 +287,7 @@
280
287
  const viewMode = ref(OrientationToolsViewMode.TWO_D);
281
288
  const headingRef = ref(0);
282
289
  const tiltRef = ref(0);
290
+ const mobileLandscape = isMobileLandscape();
283
291
 
284
292
  const handleRenderEvent = ({ map }) => {
285
293
  viewMode.value = getViewModeForMap(map);
@@ -306,13 +314,10 @@
306
314
  return headingRef.value;
307
315
  },
308
316
  async set(headingValue) {
309
- let vp;
310
- if (viewMode.value === OrientationToolsViewMode.OBLIQUE) {
311
- vp = await app.maps.activeMap.getViewpoint();
312
- } else {
313
- vp = app.maps.activeMap.getViewpointSync();
314
- }
317
+ const vp = await app.maps.activeMap.getViewpoint();
318
+ delete vp.cameraPosition;
315
319
  vp.heading = headingValue;
320
+ vp.animate = true;
316
321
  app.maps.activeMap.gotoViewpoint(vp);
317
322
  },
318
323
  });
@@ -430,6 +435,7 @@
430
435
  homeAction,
431
436
  rotationAction,
432
437
  movementApiCallsDisabled,
438
+ mobileLandscape,
433
439
  };
434
440
  },
435
441
  };
@@ -445,7 +451,8 @@
445
451
  width: unset;
446
452
  padding: 12px;
447
453
  &.mobile {
448
- top: 1rem;
454
+ // same height as mobile Icon
455
+ padding-top: 0px;
449
456
  right: 1rem;
450
457
  bottom: auto;
451
458
  }
@@ -456,4 +463,7 @@
456
463
  margin-bottom: 0;
457
464
  }
458
465
  }
466
+ .no-zoom {
467
+ touch-action: none; /* Disable gestures like pinch and double-tap zoom */
468
+ }
459
469
  </style>
@@ -83,5 +83,6 @@ declare const _default: import("vue").DefineComponent<{}, {
83
83
  homeAction: any;
84
84
  rotationAction: any;
85
85
  movementApiCallsDisabled: import("vue").Ref<boolean>;
86
+ mobileLandscape: import("vue").ComputedRef<boolean>;
86
87
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
87
88
  export default _default;
@@ -3,6 +3,7 @@
3
3
  <v-snackbar
4
4
  v-for="notification in notifications"
5
5
  :key="notification.id"
6
+ :data-notification-id="notification.id"
6
7
  v-model="notification.open"
7
8
  :timeout="notification.timeout"
8
9
  class="vcs-notifier"
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <v-list
3
- class="ma-0 overflow-y-auto vcs-search-results results-component"
3
+ class="ma-0 overflow-y-auto results-component"
4
+ :class="xs ? 'vcs-search-results-mobile' : 'vcs-search-results'"
4
5
  v-model:selected="highlighted"
5
6
  >
6
7
  <ResultItem
@@ -8,10 +9,10 @@
8
9
  :query="query"
9
10
  class="cursor-pointer"
10
11
  :class="{
11
- 'vcs-search-result-border': index < items.length - 1,
12
+ 'vcs-search-result-border': index < renderingItems.length - 1,
12
13
  selected: index === selectedIndex,
13
14
  }"
14
- v-for="(item, index) in items"
15
+ v-for="(item, index) in renderingItems"
15
16
  :key="index"
16
17
  :value="item.value"
17
18
  />
@@ -21,6 +22,7 @@
21
22
  <script>
22
23
  import { inject, onUnmounted, ref, computed } from 'vue';
23
24
  import { VList } from 'vuetify/components';
25
+ import { useDisplay } from 'vuetify';
24
26
  import ResultItem from './ResultItem.vue';
25
27
 
26
28
  /**
@@ -48,6 +50,10 @@
48
50
  type: Number,
49
51
  default: -1,
50
52
  },
53
+ showSelectedOnly: {
54
+ type: Boolean,
55
+ default: false,
56
+ },
51
57
  },
52
58
  setup(props) {
53
59
  const items = computed(() => {
@@ -75,25 +81,43 @@
75
81
  },
76
82
  );
77
83
 
84
+ const { xs } = useDisplay();
85
+
86
+ const highlighted = computed({
87
+ get() {
88
+ return selectedRef.value;
89
+ },
90
+ set(value) {
91
+ selectedRef.value = value;
92
+ const [index] = value;
93
+ if (index >= 0) {
94
+ const item = items.value[index];
95
+ item.clicked();
96
+ }
97
+ },
98
+ });
99
+
78
100
  onUnmounted(() => {
79
101
  selectedListener();
80
102
  });
81
103
 
104
+ // Dynamically filter items based on showSelectedOnly
105
+ const renderingItems = computed(() => {
106
+ if (props.showSelectedOnly) {
107
+ const index = selectedRef.value[0];
108
+ if (index !== undefined && index !== null) {
109
+ return [items.value[index]];
110
+ } else {
111
+ return [];
112
+ }
113
+ }
114
+ return items.value;
115
+ });
116
+
82
117
  return {
83
- items,
84
- highlighted: computed({
85
- get() {
86
- return selectedRef.value;
87
- },
88
- set(value) {
89
- selectedRef.value = value;
90
- const [index] = value;
91
- if (index >= 0) {
92
- const item = items.value[index];
93
- item.clicked();
94
- }
95
- },
96
- }),
118
+ renderingItems,
119
+ highlighted,
120
+ xs,
97
121
  };
98
122
  },
99
123
  };
@@ -103,6 +127,9 @@
103
127
  .vcs-search-results {
104
128
  max-height: 400px;
105
129
  }
130
+ .vcs-search-results-mobile {
131
+ max-height: 300px;
132
+ }
106
133
  .vcs-search-result-border {
107
134
  border-bottom: thin solid;
108
135
  border-color: rgb(var(--v-theme-base-lighten-2));
@@ -11,9 +11,14 @@ declare const _default: import("vue").DefineComponent<{
11
11
  type: NumberConstructor;
12
12
  default: number;
13
13
  };
14
+ showSelectedOnly: {
15
+ type: BooleanConstructor;
16
+ default: boolean;
17
+ };
14
18
  }, {
15
- items: import("vue").ComputedRef<any[]>;
19
+ renderingItems: import("vue").ComputedRef<any[]>;
16
20
  highlighted: import("vue").WritableComputedRef<never[]>;
21
+ xs: import("vue").Ref<boolean>;
17
22
  }, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
18
23
  query: {
19
24
  type: StringConstructor;
@@ -27,8 +32,13 @@ declare const _default: import("vue").DefineComponent<{
27
32
  type: NumberConstructor;
28
33
  default: number;
29
34
  };
35
+ showSelectedOnly: {
36
+ type: BooleanConstructor;
37
+ default: boolean;
38
+ };
30
39
  }>>, {
31
40
  query: string;
32
41
  selectedIndex: number;
42
+ showSelectedOnly: boolean;
33
43
  }, {}>;
34
44
  export default _default;