@vcmap/ui 6.1.0-rc.5 → 6.1.0-rc.7
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.
- package/config/cluster.config.json +4 -13
- package/config/dev.config.json +6 -3
- package/config/splashscreen.config.json +6 -10
- package/dist/assets/{cesium-c486c93a.js → cesium-6c6aa853.js} +53 -23
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core-69b76061.js → core-52c2ef11.js} +5982 -5411
- package/dist/assets/core.js +1 -1
- package/dist/assets/{ol-7f119acb.js → ol-b0589b0c.js} +87 -37
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui-dccb9009.css +1 -0
- package/dist/assets/{ui-fba0f81d.js → ui-dccb9009.js} +16053 -15481
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +1 -1
- package/dist/assets/{vuetify-2b49bba6.css → vuetify-43a20e18.css} +1 -1
- package/dist/assets/{vuetify-2b49bba6.js → vuetify-43a20e18.js} +5004 -4958
- package/dist/assets/vuetify.js +1 -1
- package/dist/index.html +1 -1
- package/index.d.ts +2 -0
- package/index.html +1 -1
- package/index.js +1 -0
- package/package.json +6 -3
- package/plugins/@vcmap-show-case/theming-example/src/index.js +1 -0
- package/src/application/MapsGroupMobileMenu.vue +105 -0
- package/src/application/MapsGroupMobileMenu.vue.d.ts +7 -0
- package/src/application/VcsApp.vue +48 -24
- package/src/application/VcsApp.vue.d.ts +5 -2
- package/src/application/VcsContainer.vue +35 -13
- package/src/application/VcsContainer.vue.d.ts +3 -0
- package/src/application/VcsMobileMenuList.vue +118 -0
- package/src/application/VcsMobileMenuList.vue.d.ts +2 -0
- package/src/application/VcsNavbar.vue +12 -3
- package/src/application/VcsNavbarMobile.vue +218 -0
- package/src/application/VcsNavbarMobile.vue.d.ts +43 -0
- package/src/application/VcsSplashScreen.vue +39 -7
- package/src/application/VcsSplashScreen.vue.d.ts +6 -0
- package/src/application/uiConfigHelper.d.ts +12 -0
- package/src/application/uiConfigHelper.js +37 -0
- package/src/callback/closeSplashScreenCallback.js +1 -1
- package/src/callback/openSplashScreenCallback.js +1 -1
- package/src/components/buttons/VcsToolButton.vue +8 -1
- package/src/components/buttons/VcsToolButton.vue.d.ts +1 -0
- package/src/components/form-output/VcsTemplateMarkdown.vue +43 -0
- package/src/components/form-output/VcsTemplateMarkdown.vue.d.ts +9 -0
- package/src/components/lists/VcsTreeNode.vue +6 -1
- package/src/components/lists/VcsTreeview.vue +36 -2
- package/src/components/lists/VcsTreeview.vue.d.ts +1 -0
- package/src/components/lists/VcsTreeviewTitle.vue +8 -1
- package/src/contentTree/contentTreeCollection.js +1 -0
- package/src/contentTree/flightContentTreeItem.d.ts +8 -1
- package/src/contentTree/flightContentTreeItem.js +26 -3
- package/src/contentTree/groupContentTreeItem.d.ts +16 -0
- package/src/contentTree/groupContentTreeItem.js +31 -1
- package/src/contentTree/layerContentTreeItem.d.ts +8 -1
- package/src/contentTree/layerContentTreeItem.js +25 -3
- package/src/contentTree/layerGroupContentTreeItem.d.ts +6 -0
- package/src/contentTree/layerGroupContentTreeItem.js +27 -3
- package/src/contentTree/obliqueCollectionContentTreeItem.d.ts +6 -0
- package/src/contentTree/obliqueCollectionContentTreeItem.js +22 -2
- package/src/featureInfo/BalloonComponent.vue +6 -6
- package/src/featureInfo/MarkdownBalloonComponent.vue +3 -9
- package/src/featureInfo/MarkdownBalloonComponent.vue.d.ts +1 -11
- package/src/featureInfo/balloonHelper.js +1 -1
- package/src/featureInfo/featureInfo.js +2 -3
- package/src/featureInfo/markdownBalloonFeatureInfoView.d.ts +0 -6
- package/src/featureInfo/markdownBalloonFeatureInfoView.js +5 -14
- package/src/featureInfo/markdownFeatureInfoView.d.ts +2 -8
- package/src/featureInfo/markdownFeatureInfoView.js +6 -15
- package/src/i18n/de.d.ts +58 -50
- package/src/i18n/de.js +5 -0
- package/src/i18n/en.d.ts +58 -50
- package/src/i18n/en.js +5 -0
- package/src/legend/VcsLegend.vue +21 -2
- package/src/legend/VcsLegend.vue.d.ts +1 -0
- package/src/legend/legendHelper.d.ts +0 -13
- package/src/legend/legendHelper.js +3 -27
- package/src/manager/navbarManager.d.ts +14 -1
- package/src/manager/navbarManager.js +22 -2
- package/src/manager/toolbox/GroupToolboxComponent.vue +16 -3
- package/src/manager/toolbox/GroupToolboxComponent.vue.d.ts +1 -0
- package/src/manager/toolbox/SelectToolboxComponent.vue +15 -3
- package/src/manager/toolbox/SelectToolboxComponent.vue.d.ts +1 -0
- package/src/manager/toolbox/ToolboxManagerComponent.vue +44 -14
- package/src/manager/toolbox/ToolboxManagerComponent.vue.d.ts +9 -0
- package/src/manager/toolbox/toolboxManager.d.ts +2 -1
- package/src/manager/toolbox/toolboxManager.js +13 -1
- package/src/manager/window/WindowComponent.vue +3 -2
- package/src/manager/window/WindowComponentHeader.vue +9 -1
- package/src/manager/window/WindowComponentHeader.vue.d.ts +1 -0
- package/src/manager/window/WindowManager.vue +175 -30
- package/src/manager/window/WindowManager.vue.d.ts +5 -0
- package/src/navigation/MapNavigation.vue +27 -19
- package/src/navigation/MapNavigation.vue.d.ts +1 -0
- package/src/search/ResultsComponent.vue +44 -17
- package/src/search/ResultsComponent.vue.d.ts +11 -1
- package/src/search/SearchComponent.vue +60 -9
- package/src/search/SearchComponent.vue.d.ts +2 -0
- package/src/vuePlugins/vuetify.d.ts +4 -0
- package/src/vuePlugins/vuetify.js +49 -3
- package/dist/assets/ui-fba0f81d.css +0 -1
- /package/dist/assets/{vue-ef2b3f82.js → vue-f7a0b088.js} +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
|
-
.
|
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
|
-
.
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
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 =
|
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;
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<template>
|
2
2
|
<v-container
|
3
|
-
:class="
|
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
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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="smAndUp && !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.
|
@@ -280,6 +285,7 @@
|
|
280
285
|
const viewMode = ref(OrientationToolsViewMode.TWO_D);
|
281
286
|
const headingRef = ref(0);
|
282
287
|
const tiltRef = ref(0);
|
288
|
+
const mobileLandscape = isMobileLandscape();
|
283
289
|
|
284
290
|
const handleRenderEvent = ({ map }) => {
|
285
291
|
viewMode.value = getViewModeForMap(map);
|
@@ -306,13 +312,10 @@
|
|
306
312
|
return headingRef.value;
|
307
313
|
},
|
308
314
|
async set(headingValue) {
|
309
|
-
|
310
|
-
|
311
|
-
vp = await app.maps.activeMap.getViewpoint();
|
312
|
-
} else {
|
313
|
-
vp = app.maps.activeMap.getViewpointSync();
|
314
|
-
}
|
315
|
+
const vp = await app.maps.activeMap.getViewpoint();
|
316
|
+
delete vp.cameraPosition;
|
315
317
|
vp.heading = headingValue;
|
318
|
+
vp.animate = true;
|
316
319
|
app.maps.activeMap.gotoViewpoint(vp);
|
317
320
|
},
|
318
321
|
});
|
@@ -430,6 +433,7 @@
|
|
430
433
|
homeAction,
|
431
434
|
rotationAction,
|
432
435
|
movementApiCallsDisabled,
|
436
|
+
mobileLandscape,
|
433
437
|
};
|
434
438
|
},
|
435
439
|
};
|
@@ -445,7 +449,8 @@
|
|
445
449
|
width: unset;
|
446
450
|
padding: 12px;
|
447
451
|
&.mobile {
|
448
|
-
|
452
|
+
// same height as mobile Icon
|
453
|
+
padding-top: 0px;
|
449
454
|
right: 1rem;
|
450
455
|
bottom: auto;
|
451
456
|
}
|
@@ -456,4 +461,7 @@
|
|
456
461
|
margin-bottom: 0;
|
457
462
|
}
|
458
463
|
}
|
464
|
+
.no-zoom {
|
465
|
+
touch-action: none; /* Disable gestures like pinch and double-tap zoom */
|
466
|
+
}
|
459
467
|
</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;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<template>
|
2
2
|
<v-list
|
3
|
-
class="ma-0 overflow-y-auto
|
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 <
|
12
|
+
'vcs-search-result-border': index < renderingItems.length - 1,
|
12
13
|
selected: index === selectedIndex,
|
13
14
|
}"
|
14
|
-
v-for="(item, index) in
|
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
|
-
|
84
|
-
highlighted
|
85
|
-
|
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
|
-
|
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;
|