@vcmap/ui 6.0.11 → 6.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/base.config.json +25 -3
- package/config/dev.config.json +17 -3
- package/config/splashscreen.config.json +13 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core-d78889f9.js → core-9d0cfec3.js} +6949 -5868
- package/dist/assets/core.js +1 -1
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui-08446666.css +1 -0
- package/dist/assets/{ui-f56287eb.js → ui-08446666.js} +17374 -19067
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +1 -1
- package/dist/assets/{vuetify-03bc5f58.js → vuetify-67025c41.js} +1 -1
- package/dist/assets/vuetify.js +1 -1
- package/index.d.ts +11 -1
- package/index.js +6 -0
- package/package.json +2 -2
- package/plugins/@vcmap-show-case/dev-tools/package.json +5 -0
- package/plugins/@vcmap-show-case/dev-tools/src/eventLogger.js +35 -0
- package/plugins/@vcmap-show-case/dev-tools/src/index.js +59 -0
- package/plugins/@vcmap-show-case/search-example/src/searchImpl.js +10 -0
- package/src/application/VcsApp.vue.d.ts +22 -0
- package/src/application/VcsContainer.vue.d.ts +15 -0
- package/src/application/VcsSplashScreen.vue +35 -28
- package/src/application/VcsSplashScreen.vue.d.ts +1 -0
- package/src/callback/addModuleCallback.d.ts +29 -0
- package/src/callback/addModuleCallback.js +61 -0
- package/src/callback/removeModuleCallback.d.ts +29 -0
- package/src/callback/removeModuleCallback.js +53 -0
- package/src/callback/startRotationCallback.d.ts +37 -0
- package/src/callback/startRotationCallback.js +67 -0
- package/src/callback/stopRotationCallback.d.ts +8 -0
- package/src/callback/stopRotationCallback.js +37 -0
- package/src/components/icons/+all.js +4 -0
- package/src/components/icons/View360Icon.vue +55 -0
- package/src/components/icons/View360Icon.vue.d.ts +2 -0
- package/src/components/lists/VcsTreeNode.vue +237 -0
- package/src/components/lists/VcsTreeNode.vue.d.ts +31 -0
- package/src/components/lists/VcsTreeview.vue +103 -173
- package/src/components/lists/VcsTreeview.vue.d.ts +41 -4
- package/src/components/lists/VcsTreeviewTitle.vue +10 -3
- package/src/components/lists/VcsTreeviewTitle.vue.d.ts +2 -0
- package/src/featureInfo/BalloonComponent.vue +18 -47
- package/src/featureInfo/BalloonComponent.vue.d.ts +0 -1
- package/src/featureInfo/IframeComponent.vue +1 -32
- package/src/featureInfo/IframeComponent.vue.d.ts +1 -4
- package/src/i18n/de.d.ts +1 -0
- package/src/i18n/de.js +1 -0
- package/src/i18n/en.d.ts +1 -0
- package/src/i18n/en.js +1 -0
- package/src/init.d.ts +6 -0
- package/src/init.js +26 -14
- package/src/manager/window/WindowComponent.vue +1 -1
- package/src/navigation/MapNavigation.vue +83 -1
- package/src/navigation/MapNavigation.vue.d.ts +2 -0
- package/src/search/ResultItem.vue +1 -10
- package/src/search/ResultsComponent.vue +11 -1
- package/src/search/ResultsComponent.vue.d.ts +9 -0
- package/src/search/SearchComponent.vue +88 -11
- package/src/search/SearchComponent.vue.d.ts +7 -0
- package/src/search/search.d.ts +3 -0
- package/src/search/search.js +3 -2
- package/src/uiConfig.d.ts +31 -0
- package/src/uiConfig.js +5 -0
- package/src/vuePlugins/vuetify.js +2 -0
- package/dist/assets/ui-f56287eb.css +0 -1
- /package/dist/assets/{cesium-5a0d7ac6.js → cesium-11e5bbc6.js} +0 -0
- /package/dist/assets/{ol-27d44222.js → ol-0d0ebb27.js} +0 -0
- /package/dist/assets/{vue-41556557.js → vue-2f81c7f8.js} +0 -0
- /package/dist/assets/{vuetify-03bc5f58.css → vuetify-67025c41.css} +0 -0
package/src/init.d.ts
CHANGED
@@ -11,6 +11,12 @@ export default function initApp(mountTarget: string): Promise<import("@src/vcsUi
|
|
11
11
|
* @returns {Promise<import("@src/vcsUiApp.js").default>}
|
12
12
|
*/
|
13
13
|
export function initAppFromModule(mountTarget: string, configUrl?: string | undefined): Promise<import("@src/vcsUiApp.js").default>;
|
14
|
+
/**
|
15
|
+
* Creates a module from a config object or a url
|
16
|
+
* @param {import("@vcmap/core").VcsModuleConfig|string} c
|
17
|
+
* @returns {Promise<import("@vcmap/core").VcsModule|null>}
|
18
|
+
*/
|
19
|
+
export function createModuleFromObjectOrUrl(c: import("@vcmap/core").VcsModuleConfig | string): Promise<import("@vcmap/core").VcsModule | null>;
|
14
20
|
/**
|
15
21
|
* Initializes app with a map config containing a set of config urls
|
16
22
|
* @param {string} mountTarget
|
package/src/init.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import { createApp } from 'vue';
|
2
2
|
import { check, is, maybe, oneOf, optional } from '@vcsuite/check';
|
3
3
|
import { VcsModule } from '@vcmap/core';
|
4
|
+
import { getLogger } from '@vcsuite/logger';
|
4
5
|
import VcsAppComponentWrapper from './application/VcsAppWrapper.vue';
|
5
6
|
import VcsUiApp from './vcsUiApp.js';
|
6
7
|
import { createSafeI18n } from './vuePlugins/i18n.js';
|
@@ -76,6 +77,30 @@ export async function initAppFromModule(mountTarget, configUrl) {
|
|
76
77
|
return app;
|
77
78
|
}
|
78
79
|
|
80
|
+
/**
|
81
|
+
* Creates a module from a config object or a url
|
82
|
+
* @param {import("@vcmap/core").VcsModuleConfig|string} c
|
83
|
+
* @returns {Promise<import("@vcmap/core").VcsModule|null>}
|
84
|
+
*/
|
85
|
+
export async function createModuleFromObjectOrUrl(c) {
|
86
|
+
if (is(c, Object)) {
|
87
|
+
if (!is(c, VcsUiAppConfigPattern)) {
|
88
|
+
getLogger('init').warning(
|
89
|
+
'Provided object is no valid VcsUiAppConfig',
|
90
|
+
c,
|
91
|
+
);
|
92
|
+
}
|
93
|
+
return new VcsModule(/** @type{import("@vcmap/core").VcsModuleConfig} */ c);
|
94
|
+
} else if (is(c, String)) {
|
95
|
+
const response = await fetch(c);
|
96
|
+
if (response.ok) {
|
97
|
+
const config = await response.json();
|
98
|
+
return new VcsModule(config);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
return null;
|
102
|
+
}
|
103
|
+
|
79
104
|
/**
|
80
105
|
* Initializes app with a map config containing a set of config urls
|
81
106
|
* @param {string} mountTarget
|
@@ -95,20 +120,7 @@ export async function initAppFromAppConfig(mountTarget, appUrl) {
|
|
95
120
|
check(appConfig.modules, [oneOf(String, Object)]);
|
96
121
|
|
97
122
|
const modules = await Promise.all(
|
98
|
-
appConfig.modules.map(
|
99
|
-
if (is(c, VcsUiAppConfigPattern)) {
|
100
|
-
return new VcsModule(
|
101
|
-
/** @type{import("@vcmap/core").VcsModuleConfig} */ c,
|
102
|
-
);
|
103
|
-
} else if (is(c, String)) {
|
104
|
-
const response = await fetch(c);
|
105
|
-
if (response.ok) {
|
106
|
-
const config = await response.json();
|
107
|
-
return new VcsModule(config);
|
108
|
-
}
|
109
|
-
}
|
110
|
-
return null;
|
111
|
-
}),
|
123
|
+
appConfig.modules.map(createModuleFromObjectOrUrl),
|
112
124
|
);
|
113
125
|
// eslint-disable-next-line no-restricted-syntax
|
114
126
|
for await (const module of modules) {
|
@@ -36,6 +36,15 @@
|
|
36
36
|
<v-row justify="center" v-if="is3D && mdAndUp">
|
37
37
|
<TiltSlider v-model="tilt" :disabled="movementApiCallsDisabled" />
|
38
38
|
</v-row>
|
39
|
+
<v-row v-if="!hideRotationButton && is3D" justify="center">
|
40
|
+
<OrientationToolsButton
|
41
|
+
:icon="rotationAction.icon"
|
42
|
+
:tooltip="rotationAction.title"
|
43
|
+
:color="rotationAction.active ? 'primary' : undefined"
|
44
|
+
@click.stop="rotationAction.callback($event)"
|
45
|
+
:disabled="rotationAction.disabled"
|
46
|
+
/>
|
47
|
+
</v-row>
|
39
48
|
<v-row justify="center">
|
40
49
|
<OrientationToolsButton
|
41
50
|
v-if="homeAction.icon"
|
@@ -60,7 +69,13 @@
|
|
60
69
|
|
61
70
|
<script>
|
62
71
|
import { computed, inject, ref, reactive, onUnmounted } from 'vue';
|
63
|
-
import {
|
72
|
+
import {
|
73
|
+
ObliqueMap,
|
74
|
+
CesiumMap,
|
75
|
+
ObliqueViewDirection,
|
76
|
+
startRotation,
|
77
|
+
rotationMapControlSymbol,
|
78
|
+
} from '@vcmap/core';
|
64
79
|
import { VContainer, VRow } from 'vuetify/components';
|
65
80
|
import { useDisplay } from 'vuetify';
|
66
81
|
import { Math as CesiumMath } from '@vcmap-cesium/engine';
|
@@ -125,6 +140,59 @@
|
|
125
140
|
return { action, destroy: () => listener?.() };
|
126
141
|
}
|
127
142
|
|
143
|
+
/**
|
144
|
+
* @description Creates a rotate-around-center action to continuously rotate the viewpoint around the current map center at a specified speed. The action can be toggled on or off.
|
145
|
+
* @param {import("@src/vcsUiApp.js").default} app - The app instance containing the active map.
|
146
|
+
* @param {import("vue").ComputedRef<number>} defaultTimePerRotation - A computed property representing the time it takes to complete one rotation. The value should be a number representing seconds per rotation. Default is 60 seconds per rotation.
|
147
|
+
* @returns {{ action: import("vue").Reactive<VcsAction>, destroy: function():void }} - Returns the rotation action and a destroy method to stop the rotation listener if active.
|
148
|
+
*/
|
149
|
+
function setupRotationButton(app, defaultTimePerRotation) {
|
150
|
+
let stopRotation;
|
151
|
+
const action = reactive({
|
152
|
+
name: 'rotate-action',
|
153
|
+
title: 'navigation.rotateButton',
|
154
|
+
icon: '$vcsView360',
|
155
|
+
active: false,
|
156
|
+
callback: async () => {
|
157
|
+
if (action.active) {
|
158
|
+
if (stopRotation) {
|
159
|
+
stopRotation();
|
160
|
+
} else {
|
161
|
+
app.maps.resetExclusiveMapControls();
|
162
|
+
}
|
163
|
+
} else {
|
164
|
+
stopRotation = await startRotation(
|
165
|
+
app,
|
166
|
+
undefined,
|
167
|
+
defaultTimePerRotation.value,
|
168
|
+
);
|
169
|
+
}
|
170
|
+
},
|
171
|
+
});
|
172
|
+
|
173
|
+
const rotationListener =
|
174
|
+
app.maps.exclusiveMapControlsChanged.addEventListener((eventData) => {
|
175
|
+
const { options, id } = eventData;
|
176
|
+
action.active =
|
177
|
+
id === rotationMapControlSymbol &&
|
178
|
+
options.keyEvents === true &&
|
179
|
+
options.apiCalls === true &&
|
180
|
+
options.pointerEvents === true;
|
181
|
+
action.disabled =
|
182
|
+
id !== rotationMapControlSymbol &&
|
183
|
+
options.keyEvents === true &&
|
184
|
+
options.apiCalls === true &&
|
185
|
+
options.pointerEvents === true;
|
186
|
+
});
|
187
|
+
return {
|
188
|
+
action,
|
189
|
+
destroy: () => {
|
190
|
+
stopRotation();
|
191
|
+
rotationListener();
|
192
|
+
},
|
193
|
+
};
|
194
|
+
}
|
195
|
+
|
128
196
|
/**
|
129
197
|
* @enum {string}
|
130
198
|
*/
|
@@ -306,6 +374,17 @@
|
|
306
374
|
|
307
375
|
const { action: homeAction, destroy: homeDestroy } = setupHomeButton(app);
|
308
376
|
|
377
|
+
const defaultTimePerRotation = computed(() => {
|
378
|
+
return app.uiConfig.config?.timePerRotation;
|
379
|
+
});
|
380
|
+
|
381
|
+
const { action: rotationAction, destroy: rotationDestroy } =
|
382
|
+
setupRotationButton(app, defaultTimePerRotation);
|
383
|
+
|
384
|
+
const hideRotationButton = computed(() => {
|
385
|
+
return app.uiConfig.config?.hideRotationButton;
|
386
|
+
});
|
387
|
+
|
309
388
|
onUnmounted(() => {
|
310
389
|
if (overviewDestroy) {
|
311
390
|
overviewDestroy();
|
@@ -316,6 +395,7 @@
|
|
316
395
|
if (homeDestroy) {
|
317
396
|
homeDestroy();
|
318
397
|
}
|
398
|
+
rotationDestroy();
|
319
399
|
postRenderHandler();
|
320
400
|
overviewMapListeners.forEach((cb) => cb());
|
321
401
|
removeMovementDisabledListener();
|
@@ -346,7 +426,9 @@
|
|
346
426
|
locatorAction: reactive(locatorAction),
|
347
427
|
showOverviewButton,
|
348
428
|
showLocatorButton,
|
429
|
+
hideRotationButton,
|
349
430
|
homeAction,
|
431
|
+
rotationAction,
|
350
432
|
movementApiCallsDisabled,
|
351
433
|
};
|
352
434
|
},
|
@@ -79,7 +79,9 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
79
79
|
};
|
80
80
|
showOverviewButton: import("vue").Ref<boolean>;
|
81
81
|
showLocatorButton: import("vue").Ref<boolean>;
|
82
|
+
hideRotationButton: import("vue").ComputedRef<boolean | undefined>;
|
82
83
|
homeAction: any;
|
84
|
+
rotationAction: any;
|
83
85
|
movementApiCallsDisabled: import("vue").Ref<boolean>;
|
84
86
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
|
85
87
|
export default _default;
|
@@ -10,9 +10,6 @@
|
|
10
10
|
<span v-html="marked" />
|
11
11
|
</v-list-item-title>
|
12
12
|
</template>
|
13
|
-
<v-tooltip activator="parent">
|
14
|
-
{{ $st('search.select') }}
|
15
|
-
</v-tooltip>
|
16
13
|
<template #append>
|
17
14
|
<VcsActionButtonList
|
18
15
|
v-if="hasActions"
|
@@ -26,12 +23,7 @@
|
|
26
23
|
|
27
24
|
<script>
|
28
25
|
import { computed } from 'vue';
|
29
|
-
import {
|
30
|
-
VIcon,
|
31
|
-
VListItem,
|
32
|
-
VListItemTitle,
|
33
|
-
VTooltip,
|
34
|
-
} from 'vuetify/components';
|
26
|
+
import { VIcon, VListItem, VListItemTitle } from 'vuetify/components';
|
35
27
|
import DOMPurify from 'dompurify';
|
36
28
|
import VcsActionButtonList from '../components/buttons/VcsActionButtonList.vue';
|
37
29
|
import { markText } from './markText.js';
|
@@ -50,7 +42,6 @@
|
|
50
42
|
VIcon,
|
51
43
|
VListItem,
|
52
44
|
VListItemTitle,
|
53
|
-
VTooltip,
|
54
45
|
},
|
55
46
|
props: {
|
56
47
|
query: {
|
@@ -7,7 +7,10 @@
|
|
7
7
|
:item="item"
|
8
8
|
:query="query"
|
9
9
|
class="cursor-pointer"
|
10
|
-
:class="{
|
10
|
+
:class="{
|
11
|
+
'vcs-search-result-border': index < items.length - 1,
|
12
|
+
selected: index === selectedIndex,
|
13
|
+
}"
|
11
14
|
v-for="(item, index) in items"
|
12
15
|
:key="index"
|
13
16
|
:value="item.value"
|
@@ -41,6 +44,10 @@
|
|
41
44
|
type: Array,
|
42
45
|
required: true,
|
43
46
|
},
|
47
|
+
selectedIndex: {
|
48
|
+
type: Number,
|
49
|
+
default: -1,
|
50
|
+
},
|
44
51
|
},
|
45
52
|
setup(props) {
|
46
53
|
const items = computed(() => {
|
@@ -100,4 +107,7 @@
|
|
100
107
|
border-bottom: thin solid;
|
101
108
|
border-color: rgb(var(--v-theme-base-lighten-2));
|
102
109
|
}
|
110
|
+
.selected {
|
111
|
+
background-color: rgb(var(--v-theme-base-lighten-4));
|
112
|
+
}
|
103
113
|
</style>
|
@@ -7,6 +7,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
7
7
|
type: ArrayConstructor;
|
8
8
|
required: true;
|
9
9
|
};
|
10
|
+
selectedIndex: {
|
11
|
+
type: NumberConstructor;
|
12
|
+
default: number;
|
13
|
+
};
|
10
14
|
}, {
|
11
15
|
items: import("vue").ComputedRef<any[]>;
|
12
16
|
highlighted: import("vue").WritableComputedRef<never[]>;
|
@@ -19,7 +23,12 @@ declare const _default: import("vue").DefineComponent<{
|
|
19
23
|
type: ArrayConstructor;
|
20
24
|
required: true;
|
21
25
|
};
|
26
|
+
selectedIndex: {
|
27
|
+
type: NumberConstructor;
|
28
|
+
default: number;
|
29
|
+
};
|
22
30
|
}>>, {
|
23
31
|
query: string;
|
32
|
+
selectedIndex: number;
|
24
33
|
}, {}>;
|
25
34
|
export default _default;
|
@@ -10,20 +10,33 @@
|
|
10
10
|
:loading="searching"
|
11
11
|
clearable
|
12
12
|
:placeholder="$t('search.placeholder')"
|
13
|
-
v-model
|
13
|
+
v-model="query"
|
14
14
|
@keydown.enter="search"
|
15
|
-
@
|
15
|
+
@keydown.down.stop.prevent="selectSuggestion(1)"
|
16
|
+
@keydown.up.stop.prevent="selectSuggestion(-1)"
|
17
|
+
@input="onInput"
|
16
18
|
@click:clear="reset"
|
17
19
|
/>
|
18
20
|
</span>
|
19
|
-
<
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
<
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
<template v-if="results.length > 0">
|
22
|
+
<v-divider class="mt-1 base-darken-1" />
|
23
|
+
<ResultsComponent :query="query" :results="results" />
|
24
|
+
<v-divider />
|
25
|
+
<div class="d-flex px-2 pt-2 pb-1 justify-end">
|
26
|
+
<VcsFormButton @click="zoomToAll" variant="outlined">
|
27
|
+
{{ $t('search.zoomToAll') }}
|
28
|
+
</VcsFormButton>
|
29
|
+
</div>
|
30
|
+
</template>
|
31
|
+
<template v-else-if="suggestions.length > 0">
|
32
|
+
<v-divider class="mt-1 base-darken-1" />
|
33
|
+
<ResultsComponent
|
34
|
+
class="suggestions"
|
35
|
+
:results="suggestions"
|
36
|
+
:query="query"
|
37
|
+
:selected-index="selectedSuggestion"
|
38
|
+
/>
|
39
|
+
</template>
|
27
40
|
</v-sheet>
|
28
41
|
</template>
|
29
42
|
|
@@ -31,14 +44,20 @@
|
|
31
44
|
:deep(.v-field .v-field__outline *) {
|
32
45
|
border-color: transparent !important;
|
33
46
|
}
|
47
|
+
|
34
48
|
.user-select-none {
|
35
49
|
user-select: none;
|
36
50
|
}
|
51
|
+
|
52
|
+
.suggestions {
|
53
|
+
font-style: italic;
|
54
|
+
}
|
37
55
|
</style>
|
38
56
|
|
39
57
|
<script>
|
40
58
|
import { inject, onUnmounted, ref, computed } from 'vue';
|
41
59
|
import { getLogger } from '@vcsuite/logger';
|
60
|
+
import { v4 as uuid } from 'uuid';
|
42
61
|
import { VSheet, VDivider, VIcon } from 'vuetify/components';
|
43
62
|
import VcsTextField from '../components/form-inputs-controls/VcsTextField.vue';
|
44
63
|
import ResultsComponent from './ResultsComponent.vue';
|
@@ -62,26 +81,63 @@
|
|
62
81
|
/** @type {import("@src/vcsUiApp.js").default} */
|
63
82
|
const app = inject('vcsApp');
|
64
83
|
const searching = ref(false);
|
84
|
+
const suggesting = ref('');
|
65
85
|
const query = ref(null);
|
66
86
|
const suggestions = ref([]);
|
87
|
+
const selectedSuggestion = ref(-1);
|
67
88
|
const results = app.search.currentResults;
|
89
|
+
let queryPreSuggestion = '';
|
90
|
+
|
91
|
+
let suggestionTimeout;
|
92
|
+
|
93
|
+
const onInput = () => {
|
94
|
+
app.search.clearResults();
|
95
|
+
const trimmedInput = query.value?.trim() ?? '';
|
96
|
+
if (trimmedInput.length > 0) {
|
97
|
+
const requestId = uuid();
|
98
|
+
if (suggestionTimeout) {
|
99
|
+
clearTimeout(suggestionTimeout);
|
100
|
+
}
|
101
|
+
suggestionTimeout = setTimeout(() => {
|
102
|
+
suggesting.value = requestId;
|
103
|
+
queryPreSuggestion = trimmedInput;
|
104
|
+
selectedSuggestion.value = -1;
|
105
|
+
app.search.suggest(trimmedInput).then((s) => {
|
106
|
+
if (suggesting.value === requestId) {
|
107
|
+
suggestions.value = s;
|
108
|
+
suggesting.value = '';
|
109
|
+
}
|
110
|
+
});
|
111
|
+
}, 200);
|
112
|
+
} else {
|
113
|
+
selectedSuggestion.value = -1;
|
114
|
+
suggesting.value = '';
|
115
|
+
suggestions.value = [];
|
116
|
+
queryPreSuggestion = '';
|
117
|
+
}
|
118
|
+
};
|
68
119
|
|
69
120
|
const reset = () => {
|
70
121
|
app.search.clearResults();
|
122
|
+
selectedSuggestion.value = -1;
|
123
|
+
suggesting.value = '';
|
71
124
|
suggestions.value = [];
|
125
|
+
queryPreSuggestion = '';
|
72
126
|
};
|
73
127
|
|
74
128
|
const clear = () => {
|
75
129
|
reset();
|
76
130
|
searching.value = false;
|
131
|
+
suggestions.value = [];
|
77
132
|
query.value = null;
|
133
|
+
queryPreSuggestion = '';
|
78
134
|
};
|
79
135
|
|
80
136
|
const search = async () => {
|
81
137
|
reset();
|
82
138
|
searching.value = true;
|
83
139
|
try {
|
84
|
-
await app.search.search(query.value);
|
140
|
+
await app.search.search(query.value.trim());
|
85
141
|
} catch (e) {
|
86
142
|
getLogger('Search').error(e);
|
87
143
|
}
|
@@ -109,6 +165,27 @@
|
|
109
165
|
search,
|
110
166
|
zoomToAll,
|
111
167
|
searchIconSize,
|
168
|
+
suggestions: computed(() =>
|
169
|
+
suggestions.value.map((s) => ({
|
170
|
+
title: s,
|
171
|
+
clicked() {
|
172
|
+
query.value = s;
|
173
|
+
search();
|
174
|
+
},
|
175
|
+
})),
|
176
|
+
),
|
177
|
+
selectedSuggestion,
|
178
|
+
onInput,
|
179
|
+
selectSuggestion(value) {
|
180
|
+
const newSelection = selectedSuggestion.value + value;
|
181
|
+
if (newSelection > -1 && newSelection < suggestions.value?.length) {
|
182
|
+
selectedSuggestion.value = newSelection;
|
183
|
+
query.value = suggestions.value[newSelection];
|
184
|
+
} else {
|
185
|
+
selectedSuggestion.value = -1;
|
186
|
+
query.value = queryPreSuggestion;
|
187
|
+
}
|
188
|
+
},
|
112
189
|
};
|
113
190
|
},
|
114
191
|
};
|
@@ -7,5 +7,12 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
7
7
|
search: () => Promise<void>;
|
8
8
|
zoomToAll: () => void;
|
9
9
|
searchIconSize: import("vue").ComputedRef<number>;
|
10
|
+
suggestions: import("vue").ComputedRef<{
|
11
|
+
title: never;
|
12
|
+
clicked(): void;
|
13
|
+
}[]>;
|
14
|
+
selectedSuggestion: import("vue").Ref<number>;
|
15
|
+
onInput: () => void;
|
16
|
+
selectSuggestion(value: any): void;
|
10
17
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
|
11
18
|
export default _default;
|
package/src/search/search.d.ts
CHANGED
@@ -25,6 +25,9 @@ export type SearchImpl = {
|
|
25
25
|
*/
|
26
26
|
name: string;
|
27
27
|
search: (arg0: string) => Promise<Array<ResultItem>>;
|
28
|
+
/**
|
29
|
+
* - optional, provides suggestions for autocomplete.
|
30
|
+
*/
|
28
31
|
suggest?: ((arg0: string) => Promise<Array<string>>) | undefined;
|
29
32
|
/**
|
30
33
|
* - should abort any ongoing requests to search or suggest without throwing an error
|
package/src/search/search.js
CHANGED
@@ -35,8 +35,8 @@ import { getViewpointFromFeature } from '../actions/actionHelper.js';
|
|
35
35
|
* @typedef {Object} SearchImpl
|
36
36
|
* @property {string} name Name of the implementation. Must be unique, best practice is to prefix with your plugin name to ensure uniqueness or use a uuid.
|
37
37
|
* @property {function(string):Promise<Array<ResultItem>>} search
|
38
|
-
* @property {function(string):Promise<Array<string>>} [suggest]
|
39
|
-
* @property{function():void} abort - should abort any ongoing requests to search or suggest without throwing an error
|
38
|
+
* @property {function(string):Promise<Array<string>>} [suggest] - optional, provides suggestions for autocomplete.
|
39
|
+
* @property {function():void} abort - should abort any ongoing requests to search or suggest without throwing an error
|
40
40
|
* @property {function():void} destroy
|
41
41
|
*/
|
42
42
|
|
@@ -257,6 +257,7 @@ class Search extends IndexedCollection {
|
|
257
257
|
* @returns {Promise<Array<string>>}
|
258
258
|
*/
|
259
259
|
async suggest(q) {
|
260
|
+
this.clearResults();
|
260
261
|
const promises = await Promise.allSettled(
|
261
262
|
[...this._array].map((impl) => {
|
262
263
|
if (impl.suggest) {
|
package/src/uiConfig.d.ts
CHANGED
@@ -15,6 +15,9 @@ export type SplashScreen = {
|
|
15
15
|
name?: string | undefined;
|
16
16
|
checkBoxText?: string | undefined;
|
17
17
|
buttonTitle?: string | undefined;
|
18
|
+
secondaryButtonTitle?: string | undefined;
|
19
|
+
exitCallbackOptions?: import("./callback/vcsCallback.js").VcsCallbackOptions[] | undefined;
|
20
|
+
secondaryCallbackOptions?: import("./callback/vcsCallback.js").VcsCallbackOptions[] | undefined;
|
18
21
|
menuEntry?: boolean | undefined;
|
19
22
|
acceptInput?: boolean | undefined;
|
20
23
|
position?: {
|
@@ -92,6 +95,14 @@ export type UiConfigObject = {
|
|
92
95
|
* - an optional flag whether to show the Locator in the map.
|
93
96
|
*/
|
94
97
|
showLocator?: boolean | undefined;
|
98
|
+
/**
|
99
|
+
* - an optional flag to hide the Rotator in the map.
|
100
|
+
*/
|
101
|
+
hideRotationButton?: boolean | undefined;
|
102
|
+
/**
|
103
|
+
* - an optional flag that describes the time per rotation in seconds.
|
104
|
+
*/
|
105
|
+
timePerRotation?: number | undefined;
|
95
106
|
/**
|
96
107
|
* - can be used to hide the default Header of the map
|
97
108
|
*/
|
@@ -178,6 +189,9 @@ export type UiConfigObject = {
|
|
178
189
|
* @property {string} [name]
|
179
190
|
* @property {string} [checkBoxText]
|
180
191
|
* @property {string} [buttonTitle]
|
192
|
+
* @property {string} [secondaryButtonTitle]
|
193
|
+
* @property {Array<import("./callback/vcsCallback.js").VcsCallbackOptions>} [exitCallbackOptions]
|
194
|
+
* @property {Array<import("./callback/vcsCallback.js").VcsCallbackOptions>} [secondaryCallbackOptions]
|
181
195
|
* @property {boolean} [menuEntry]
|
182
196
|
* @property {boolean} [acceptInput]
|
183
197
|
* @property {Object} [position]
|
@@ -211,6 +225,8 @@ export type UiConfigObject = {
|
|
211
225
|
* @property {string} [favicon] - the favicon to set
|
212
226
|
* @property {string} [headerTitle] - the title to display in the tab of the browser
|
213
227
|
* @property {boolean} [showLocator] - an optional flag whether to show the Locator in the map.
|
228
|
+
* @property {boolean} [hideRotationButton] - an optional flag to hide the Rotator in the map.
|
229
|
+
* @property {number} [timePerRotation] - an optional flag that describes the time per rotation in seconds.
|
214
230
|
* @property {boolean} [hideHeader] - can be used to hide the default Header of the map
|
215
231
|
* @property {boolean} [hideSearch] - can be used to hide the integrated Search bar
|
216
232
|
* @property {boolean} [hideMapButtons] - can be used to hide the default Map Buttons
|
@@ -345,6 +361,13 @@ declare class UiConfig extends Collection<UiConfigurationItem<unknown>> {
|
|
345
361
|
readonly name?: string | undefined;
|
346
362
|
readonly checkBoxText?: string | undefined;
|
347
363
|
readonly buttonTitle?: string | undefined;
|
364
|
+
readonly secondaryButtonTitle?: string | undefined;
|
365
|
+
readonly exitCallbackOptions?: readonly {
|
366
|
+
readonly type: string;
|
367
|
+
}[] | undefined;
|
368
|
+
readonly secondaryCallbackOptions?: readonly {
|
369
|
+
readonly type: string;
|
370
|
+
}[] | undefined;
|
348
371
|
readonly menuEntry?: boolean | undefined;
|
349
372
|
readonly acceptInput?: boolean | undefined;
|
350
373
|
readonly position?: {
|
@@ -417,6 +440,14 @@ declare class UiConfig extends Collection<UiConfigurationItem<unknown>> {
|
|
417
440
|
* - an optional flag whether to show the Locator in the map.
|
418
441
|
*/
|
419
442
|
readonly showLocator?: boolean | undefined;
|
443
|
+
/**
|
444
|
+
* - an optional flag to hide the Rotator in the map.
|
445
|
+
*/
|
446
|
+
readonly hideRotationButton?: boolean | undefined;
|
447
|
+
/**
|
448
|
+
* - an optional flag that describes the time per rotation in seconds.
|
449
|
+
*/
|
450
|
+
readonly timePerRotation?: number | undefined;
|
420
451
|
/**
|
421
452
|
* - can be used to hide the default Header of the map
|
422
453
|
*/
|
package/src/uiConfig.js
CHANGED
@@ -24,6 +24,9 @@ import { reactive, readonly } from 'vue';
|
|
24
24
|
* @property {string} [name]
|
25
25
|
* @property {string} [checkBoxText]
|
26
26
|
* @property {string} [buttonTitle]
|
27
|
+
* @property {string} [secondaryButtonTitle]
|
28
|
+
* @property {Array<import("./callback/vcsCallback.js").VcsCallbackOptions>} [exitCallbackOptions]
|
29
|
+
* @property {Array<import("./callback/vcsCallback.js").VcsCallbackOptions>} [secondaryCallbackOptions]
|
27
30
|
* @property {boolean} [menuEntry]
|
28
31
|
* @property {boolean} [acceptInput]
|
29
32
|
* @property {Object} [position]
|
@@ -59,6 +62,8 @@ import { reactive, readonly } from 'vue';
|
|
59
62
|
* @property {string} [favicon] - the favicon to set
|
60
63
|
* @property {string} [headerTitle] - the title to display in the tab of the browser
|
61
64
|
* @property {boolean} [showLocator] - an optional flag whether to show the Locator in the map.
|
65
|
+
* @property {boolean} [hideRotationButton] - an optional flag to hide the Rotator in the map.
|
66
|
+
* @property {number} [timePerRotation] - an optional flag that describes the time per rotation in seconds.
|
62
67
|
* @property {boolean} [hideHeader] - can be used to hide the default Header of the map
|
63
68
|
* @property {boolean} [hideSearch] - can be used to hide the integrated Search bar
|
64
69
|
* @property {boolean} [hideMapButtons] - can be used to hide the default Map Buttons
|
@@ -89,6 +89,7 @@ export function createVcsThemes(options, primaryColor) {
|
|
89
89
|
'hover-opacity': 0.16,
|
90
90
|
'high-emphasis-opacity': 1,
|
91
91
|
'medium-emphasis-opacity': 1,
|
92
|
+
'list-item-subtitle-opacity': 0.6,
|
92
93
|
'vcs-font-size': '13px',
|
93
94
|
'vcs-font-family': 'Titillium Web',
|
94
95
|
...options?.light?.variables,
|
@@ -119,6 +120,7 @@ export function createVcsThemes(options, primaryColor) {
|
|
119
120
|
'hover-opacity': 0.16,
|
120
121
|
'high-emphasis-opacity': 1,
|
121
122
|
'medium-emphasis-opacity': 1,
|
123
|
+
'list-item-subtitle-opacity': 0.6,
|
122
124
|
'vcs-font-size': '13px',
|
123
125
|
'vcs-font-family': 'Titillium Web',
|
124
126
|
...options?.dark?.variables,
|