@vcmap/ui 5.0.0-rc.14 → 5.0.0-rc.16

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 (132) hide show
  1. package/README.md +33 -31
  2. package/build/build.js +9 -0
  3. package/build/buildHelpers.js +12 -10
  4. package/build/commonViteConfig.js +3 -10
  5. package/config/base.config.json +30 -24
  6. package/config/dev.config.json +13 -1
  7. package/config/www.config.json +104 -17
  8. package/dist/assets/cesium.430460.js +137226 -0
  9. package/dist/assets/cesium.js +1 -1
  10. package/dist/assets/core.5089ba.js +16024 -0
  11. package/dist/assets/core.js +1 -1
  12. package/dist/assets/index.854f8e2b.js +1 -0
  13. package/dist/assets/ol.9be53a.js +44279 -0
  14. package/dist/assets/ol.js +1 -1
  15. package/dist/assets/{ui.15ef6a.css → ui.49010a.css} +1 -1
  16. package/dist/assets/ui.49010a.js +16776 -0
  17. package/dist/assets/ui.js +1 -1
  18. package/dist/assets/vue.247c1c.js +4675 -0
  19. package/dist/assets/vue.js +5 -2
  20. package/dist/assets/{vuetify.202322.css → vuetify.735e58.css} +1 -1
  21. package/dist/assets/vuetify.735e58.js +21019 -0
  22. package/dist/assets/vuetify.js +5 -2
  23. package/dist/index.html +1 -1
  24. package/index.html +77 -0
  25. package/index.js +8 -1
  26. package/package.json +12 -10
  27. package/plugins/@vcmap/create-link/fallbackCreateLink.vue +4 -1
  28. package/plugins/@vcmap/create-link/index.js +4 -1
  29. package/plugins/@vcmap/pluginExample/exampleActions.js +45 -0
  30. package/plugins/@vcmap/pluginExample/index.js +38 -1
  31. package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +152 -98
  32. package/plugins/@vcmap/project-selector/ContextsListComponent.vue +8 -1
  33. package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +27 -1
  34. package/plugins/@vcmap/search-nominatim/LICENSE.md +14 -0
  35. package/plugins/@vcmap/search-nominatim/README.md +2 -0
  36. package/plugins/@vcmap/search-nominatim/config.json +4 -0
  37. package/plugins/@vcmap/search-nominatim/index.js +26 -0
  38. package/plugins/@vcmap/search-nominatim/nominatim.js +170 -0
  39. package/plugins/@vcmap/search-nominatim/package.json +43 -0
  40. package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +26 -0
  41. package/plugins/buttonExamples/ButtonExamples.vue +28 -1
  42. package/plugins/categoryTest/Categories.vue +16 -0
  43. package/plugins/categoryTest/Category.vue +30 -4
  44. package/plugins/example/mySuperComponent.vue +12 -1
  45. package/plugins/notifier/index.js +31 -0
  46. package/plugins/notifier/notifierTester.vue +88 -0
  47. package/plugins/package.json +2 -1
  48. package/plugins/simple-graph/SimpleGraphComponent.vue +5 -11
  49. package/plugins/test/allIconsComponent.vue +16 -0
  50. package/plugins/test/editor.vue +3 -0
  51. package/plugins/test/emptyComponent.vue +3 -0
  52. package/plugins/test/index.js +22 -0
  53. package/plugins/test/myCustomHeader.vue +9 -1
  54. package/plugins/test/testList.vue +287 -0
  55. package/plugins/test/vcsContent.vue +3 -0
  56. package/plugins/test/windowManagerExample.vue +3 -0
  57. package/plugins/wizardExample/index.js +41 -0
  58. package/plugins/wizardExample/wizardExample.vue +77 -0
  59. package/src/actions/actionHelper.js +103 -2
  60. package/src/actions/styleSelector.vue +9 -0
  61. package/src/application/VcsApp.vue +95 -17
  62. package/src/application/VcsAttributions.vue +63 -0
  63. package/src/application/VcsAttributionsFooter.vue +87 -0
  64. package/src/application/{Navbar.vue → VcsNavbar.vue} +35 -2
  65. package/src/application/VcsSettings.vue +4 -0
  66. package/src/application/attributionsHelper.js +150 -0
  67. package/src/application/vcsAppWrapper.vue +5 -1
  68. package/src/components/buttons/VcsActionButtonList.vue +8 -1
  69. package/src/components/buttons/VcsButton.vue +7 -1
  70. package/src/components/form-inputs-controls/VcsCheckbox.vue +7 -2
  71. package/src/components/form-inputs-controls/VcsColorPicker.vue +4 -0
  72. package/src/components/form-inputs-controls/VcsFormSection.vue +55 -9
  73. package/src/components/form-inputs-controls/VcsRadio.vue +7 -1
  74. package/src/components/form-inputs-controls/VcsSelect.vue +38 -2
  75. package/src/components/form-inputs-controls/VcsTextArea.vue +2 -0
  76. package/src/components/form-inputs-controls/VcsTextField.vue +16 -4
  77. package/src/components/form-inputs-controls/VcsWizard.vue +133 -0
  78. package/src/components/imageElementInjector.vue +22 -0
  79. package/src/components/lists/VcsActionList.vue +12 -1
  80. package/src/components/lists/VcsList.vue +466 -0
  81. package/src/components/lists/VcsTreeview.vue +7 -3
  82. package/src/components/lists/VcsTreeviewLeaf.vue +23 -51
  83. package/src/components/lists/VcsTreeviewSearchbar.vue +6 -23
  84. package/src/components/notification/VcsTooltip.vue +14 -9
  85. package/src/components/tables/VcsTable.vue +129 -38
  86. package/src/contentTree/LayerTree.vue +1 -1
  87. package/src/contentTree/contentTreeItem.js +13 -13
  88. package/src/contentTree/subContentTreeItem.js +1 -1
  89. package/src/contentTree/vcsObjectContentTreeItem.js +1 -1
  90. package/src/featureInfo/AddressBalloonComponent.vue +17 -1
  91. package/src/featureInfo/BalloonComponent.vue +63 -27
  92. package/src/featureInfo/balloonFeatureInfoView.js +14 -14
  93. package/src/featureInfo/balloonHelper.js +4 -0
  94. package/src/featureInfo/featureInfo.js +23 -2
  95. package/src/featureInfo/featureInfoInteraction.js +1 -1
  96. package/src/i18n/de.js +22 -0
  97. package/src/i18n/en.js +22 -0
  98. package/src/icons/+all.js +4 -0
  99. package/src/icons/WandIcon.vue +63 -0
  100. package/src/legend/legendHelper.js +18 -12
  101. package/src/legend/styleLegendItem.vue +20 -1
  102. package/src/legend/vcsLegend.vue +29 -3
  103. package/src/manager/toolbox/GroupToolboxComponent.vue +13 -1
  104. package/src/manager/toolbox/SelectToolboxComponent.vue +13 -1
  105. package/src/manager/toolbox/ToolboxManager.vue +3 -0
  106. package/src/manager/window/WindowComponent.vue +15 -2
  107. package/src/manager/window/WindowComponentHeader.vue +38 -7
  108. package/src/manager/window/WindowManager.vue +1 -0
  109. package/src/manager/window/windowManager.js +11 -1
  110. package/src/navigation/mapNavigation.vue +15 -36
  111. package/src/navigation/orientationToolsButton.vue +6 -1
  112. package/src/navigation/overviewMap.js +19 -47
  113. package/src/navigation/tiltSlider.vue +3 -0
  114. package/src/navigation/vcsCompass.vue +2 -0
  115. package/src/notifier/notifier.js +121 -0
  116. package/src/notifier/notifierComponent.vue +84 -0
  117. package/src/search/resultItem.vue +89 -0
  118. package/src/search/resultsComponent.vue +98 -0
  119. package/src/search/search.js +326 -0
  120. package/src/search/searchComponent.vue +90 -0
  121. package/src/styles/_typography.scss +3 -0
  122. package/src/styles/utils/_cursor.scss +4 -0
  123. package/src/styles/variables.scss +23 -4
  124. package/src/vcsUiApp.js +35 -1
  125. package/src/vuePlugins/vuetify.js +2 -0
  126. package/dist/assets/cesium.9489f8.js +0 -8699
  127. package/dist/assets/core.aa346a.js +0 -4
  128. package/dist/assets/index.3cd4fffa.js +0 -1
  129. package/dist/assets/ol.39651b.js +0 -439
  130. package/dist/assets/ui.15ef6a.js +0 -71
  131. package/dist/assets/vue.cbe9d8.js +0 -9
  132. package/dist/assets/vuetify.202322.js +0 -148
@@ -0,0 +1,287 @@
1
+ <template>
2
+ <v-sheet>
3
+ <v-sheet class="pa-2">
4
+ <v-switch
5
+ v-model="selectable"
6
+ label="Selectable"
7
+ />
8
+ <v-switch
9
+ :disabled="!selectable"
10
+ v-model="selectSingle"
11
+ label=" Single Select"
12
+ />
13
+ <v-switch
14
+ v-model="searchable"
15
+ label="Searchable"
16
+ />
17
+ <v-dialog
18
+ v-model="dialog"
19
+ width="400"
20
+ >
21
+ <template #activator="{ on }">
22
+ <vcs-button v-on="on">
23
+ Add An item
24
+ </vcs-button>
25
+ </template>
26
+ <v-card class="pa-2">
27
+ <v-form
28
+ @submit.prevent="add"
29
+ >
30
+ <vcs-text-field
31
+ v-model="newItem.name"
32
+ label="Name"
33
+ :rules="required"
34
+ />
35
+ <vcs-text-field
36
+ v-model="newItem.title"
37
+ label="Title"
38
+ :rules="required"
39
+ />
40
+ <v-switch label="visible" v-model="newItem.visible" />
41
+ <v-switch label="disabled" v-model="newItem.disabled" />
42
+ <v-switch label="random icon" v-model="newItem.icon" />
43
+ <v-switch label="console.log action" v-model="newItem.action" />
44
+ <v-switch label="console.log on clicked" v-model="newItem.clicked" />
45
+ <v-switch label="console.log selected state" v-model="newItem.selected" />
46
+ <vcs-button
47
+ type="submit"
48
+ >
49
+ Add
50
+ </vcs-button>
51
+ </v-form>
52
+ </v-card>
53
+ </v-dialog>
54
+ <v-divider class="ma-2" />
55
+ <v-switch
56
+ v-model="showTitle"
57
+ label="Show Title"
58
+ />
59
+ <vcs-text-field v-model="title" placeholder="Title" />
60
+ <v-switch
61
+ v-model="titleActions"
62
+ label="Title Actions"
63
+ />
64
+ <v-switch
65
+ v-model="titleIcon"
66
+ label="Title Icon"
67
+ />
68
+ <v-divider class="ma-2" />
69
+ <template v-if="selectable">
70
+ <vcs-button
71
+ @click="selected = []"
72
+ >
73
+ Clear Selection
74
+ </vcs-button>
75
+ <v-switch v-model="showSelection" label="Show Selection" />
76
+ <ul v-if="showSelection">
77
+ <li
78
+ v-for="(i, index) in selected"
79
+ :key="`item-${index}`"
80
+ >
81
+ {{ i.title }}
82
+ </li>
83
+ </ul>
84
+ </template>
85
+ <v-divider class="ma-2" />
86
+ </v-sheet>
87
+
88
+ <vcs-list
89
+ :items="items"
90
+ :selectable="selectable"
91
+ :single-select="selectSingle"
92
+ :searchable="searchable"
93
+ :show-title="showTitle"
94
+ :icon="titleIconSrc"
95
+ :actions="titleActionsArray"
96
+ :title="title"
97
+ v-model="selected"
98
+ />
99
+ </v-sheet>
100
+ </template>
101
+
102
+ <script>
103
+ import { VcsList, VcsButton, VcsTextField, Icons } from '@vcmap/ui';
104
+ import {
105
+ VSwitch,
106
+ VDivider,
107
+ VSheet,
108
+ VDialog,
109
+ VCard,
110
+ VForm,
111
+ } from 'vuetify/lib';
112
+ import { computed, ref } from 'vue';
113
+
114
+ function getRandomIcon() {
115
+ const keys = Object.keys(Icons);
116
+ const index = Math.floor(keys.length * Math.random());
117
+ return `$${keys[index]}`;
118
+ }
119
+
120
+ const defaultItems = [
121
+ {
122
+ name: 'foo',
123
+ title: 'Foo',
124
+ tooltip: 'this is the foo',
125
+ icon: 'mdi-pen',
126
+ },
127
+ {
128
+ name: 'bar',
129
+ title: 'Bar',
130
+ tooltip: 'just a bar',
131
+ actions: [
132
+ {
133
+ name: 'console.log',
134
+ callback() {
135
+ console.log('bar action');
136
+ },
137
+ },
138
+ ],
139
+ },
140
+ {
141
+ name: 'bar',
142
+ title: 'Baz',
143
+ tooltip: 'special baz',
144
+ },
145
+ ];
146
+
147
+ export default {
148
+ name: 'TestList',
149
+ components: {
150
+ VcsList,
151
+ VcsButton,
152
+ VcsTextField,
153
+ VSwitch,
154
+ VDivider,
155
+ VSheet,
156
+ VDialog,
157
+ VCard,
158
+ VForm,
159
+ },
160
+ setup() {
161
+ const selectable = ref(true);
162
+ const searchable = ref(true);
163
+ const selectSingle = ref(false);
164
+ const showSelection = ref(false);
165
+ const showTitle = ref(true);
166
+ const title = ref('Title');
167
+ const titleActionsArray = ref([]);
168
+ const titleIconSrc = ref(null);
169
+ const selected = ref([]);
170
+ const items = ref(defaultItems);
171
+ const newItem = ref({
172
+ name: 'foo',
173
+ title: 'foo',
174
+ disabled: false,
175
+ visible: true,
176
+ icon: false,
177
+ action: false,
178
+ clicked: false,
179
+ selected: false,
180
+ });
181
+ const dialog = ref(false);
182
+
183
+ return {
184
+ selectable,
185
+ searchable,
186
+ selectSingle,
187
+ selected,
188
+ showSelection,
189
+ showTitle,
190
+ title,
191
+ titleActionsArray,
192
+ titleIconSrc,
193
+ items,
194
+ newItem,
195
+ dialog,
196
+ required: [
197
+ v => !!v || 'Input may not be null',
198
+ v => v.length > 0 || 'Input must have a length',
199
+ ],
200
+ add() {
201
+ const item = {
202
+ name: newItem.value.name,
203
+ title: newItem.value.title,
204
+ disabled: newItem.value.disabled,
205
+ visible: newItem.value.visible,
206
+ };
207
+
208
+ if (newItem.value.icon) {
209
+ item.icon = getRandomIcon();
210
+ }
211
+
212
+ if (newItem.value.action) {
213
+ item.actions = [
214
+ {
215
+ name: 'console.log',
216
+ callback() {
217
+ console.log('hi, i\'m: ', item.name);
218
+ },
219
+ },
220
+ ];
221
+ }
222
+
223
+ if (newItem.value.clicked) {
224
+ item.clicked = () => {
225
+ console.log(`${item.name} just got clicked`);
226
+ };
227
+ }
228
+
229
+ if (newItem.value.selected) {
230
+ item.selectionChanged = (selected) => {
231
+ if (selected) {
232
+ console.log(`${item.name} is selected`);
233
+ } else {
234
+ console.log(`${item.name} is no longer selected`);
235
+ }
236
+ };
237
+ }
238
+ items.value.push(item);
239
+ newItem.value = {
240
+ name: 'foo',
241
+ title: 'foo',
242
+ disabled: false,
243
+ visible: true,
244
+ icon: false,
245
+ action: false,
246
+ clicked: false,
247
+ selected: false,
248
+ };
249
+ dialog.value = false;
250
+ },
251
+ titleActions: computed({
252
+ get() {
253
+ return titleActionsArray.value.length > 0;
254
+ },
255
+ set(value) {
256
+ if (value) {
257
+ titleActionsArray.value = [{
258
+ name: 'console.log foo',
259
+ callback() {
260
+ console.log('foo');
261
+ },
262
+ }];
263
+ } else {
264
+ titleActionsArray.value = [];
265
+ }
266
+ },
267
+ }),
268
+ titleIcon: computed({
269
+ get() {
270
+ return !!titleIconSrc.value;
271
+ },
272
+ set(value) {
273
+ if (value) {
274
+ titleIconSrc.value = getRandomIcon();
275
+ } else {
276
+ titleIconSrc.value = null;
277
+ }
278
+ },
279
+ }),
280
+ };
281
+ },
282
+ };
283
+ </script>
284
+
285
+ <style lang="scss" scoped>
286
+
287
+ </style>
@@ -14,8 +14,11 @@
14
14
 
15
15
  </style>
16
16
  <script>
17
+ import { VSheet } from 'vuetify/lib';
18
+
17
19
  export default {
18
20
  name: 'VcsContent',
21
+ components: [VSheet],
19
22
  setup() {
20
23
  return { };
21
24
  },
@@ -51,6 +51,9 @@
51
51
  component: EmptyComponent,
52
52
  headerComponent: MyCustomHeader,
53
53
  slot: WindowSlot.DYNAMIC_RIGHT,
54
+ props: {
55
+ sample: 'A window property',
56
+ },
54
57
  },
55
58
  {
56
59
  id: 'dynamicRight2',
@@ -0,0 +1,41 @@
1
+ import { createToggleAction, ButtonLocation, WindowSlot } from '@vcmap/ui';
2
+ import WizardExample from './wizardExample.vue';
3
+
4
+ export default async () => {
5
+ return {
6
+ name: 'wizardExample',
7
+ onVcsAppMounted(app) {
8
+ const { action, destroy } = createToggleAction(
9
+ {
10
+ name: 'wizardExample',
11
+ icon: '$vcsLegend',
12
+ title: 'VCS Wizard Example',
13
+ },
14
+ {
15
+ id: 'wizard-example',
16
+ component: WizardExample,
17
+ slot: WindowSlot.DYNAMIC_LEFT,
18
+ state: {
19
+ headerTitle: 'VCS Wizard',
20
+ headerIcon: '$vcsWand',
21
+ styles: { width: '350px', height: 'auto' },
22
+ },
23
+ },
24
+ app.windowManager,
25
+ 'wizardExample',
26
+ );
27
+ app.navbarManager.add(
28
+ { id: 'wizard-example', action },
29
+ 'wizardExample',
30
+ ButtonLocation.TOOL,
31
+ );
32
+ this._destroyAction = destroy;
33
+ },
34
+ destroy() {
35
+ if (this._destroyAction) {
36
+ this._destroyAction();
37
+ this._destroyAction = null;
38
+ }
39
+ },
40
+ };
41
+ };
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <VcsWizard
3
+ v-model="step"
4
+ >
5
+ <v-stepper-step
6
+ step="1"
7
+ editable
8
+ :complete="step > 1"
9
+ >
10
+ This is the first step
11
+ </v-stepper-step>
12
+ <v-stepper-content
13
+ step="1"
14
+ >
15
+ <v-sheet>
16
+ This is the content of the first step.
17
+ </v-sheet>
18
+ <VcsButton
19
+ @click="increaseStep()"
20
+ class="my-2"
21
+ >
22
+ Next
23
+ </VcsButton>
24
+ </v-stepper-content>
25
+ <v-stepper-step
26
+ :rules="[() => false]"
27
+ step="2"
28
+ editable
29
+ >
30
+ This is the second step
31
+ </v-stepper-step>
32
+ <v-stepper-content
33
+ step="2"
34
+ >
35
+ <VcsSelect
36
+ :items="['this', 'is', 'a', 'test']"
37
+ label="Select"
38
+ class="my-2"
39
+ />
40
+ <VcsButton
41
+ @click="decreaseStep()"
42
+ >
43
+ Back
44
+ </VcsButton>
45
+ </v-stepper-content>
46
+ </VcsWizard>
47
+ </template>
48
+
49
+ <script>
50
+ import { VcsWizard, VcsButton, VcsSelect } from '@vcmap/ui';
51
+ import { VStepperStep, VStepperContent, VSheet } from 'vuetify/lib';
52
+ import { ref } from 'vue';
53
+
54
+ export default {
55
+ name: 'WizardExample',
56
+ components: {
57
+ VcsWizard,
58
+ VStepperStep,
59
+ VStepperContent,
60
+ VSheet,
61
+ VcsButton,
62
+ VcsSelect,
63
+ },
64
+ setup() {
65
+ const step = ref(1);
66
+ return {
67
+ step,
68
+ increaseStep() { step.value += 1; },
69
+ decreaseStep() { step.value -= 1; },
70
+ };
71
+ },
72
+ };
73
+ </script>
74
+
75
+ <style scoped>
76
+
77
+ </style>
@@ -1,8 +1,11 @@
1
1
  import { v4 as uuid } from 'uuid';
2
2
  import { check } from '@vcsuite/check';
3
- import { Collection, MapCollection, Viewpoint } from '@vcmap/core';
3
+ import { Collection, Extent, MapCollection, mercatorProjection, Viewpoint } from '@vcmap/core';
4
+ import { Feature } from 'ol';
5
+ import { reactive, ref } from 'vue';
4
6
  import { vcsAppSymbol } from '../pluginHelper.js';
5
- import { getWindowPositionOptions } from '../manager/window/windowManager.js';
7
+ import { getWindowPositionOptions, WindowSlot } from '../manager/window/windowManager.js';
8
+ import SearchComponent from '../search/searchComponent.vue';
6
9
 
7
10
  /**
8
11
  * @typedef {Object} ActionOptions
@@ -88,6 +91,60 @@ export function createToggleAction(actionOptions, windowComponent, windowManager
88
91
  return { action, destroy };
89
92
  }
90
93
 
94
+ /**
95
+ * Creates a toggle button for the search tool, which is only available, if at least one search implementation is registered.
96
+ * @param {VcsUiApp} app
97
+ * @returns {{ searchAction: import("vue").Ref<import("vue").UnwrapRef<VcsAction>|null>, destroy: function():void }}
98
+ */
99
+ export function createSearchButtonAction(app) {
100
+ let destroyAction = () => {};
101
+ const searchAction = ref(null);
102
+ const determineAction = () => {
103
+ if (app.windowManager.has('searchId')) {
104
+ app.windowManager.remove('searchId');
105
+ }
106
+ if (app.search.size > 0 && searchAction.value === null) {
107
+ const action = createToggleAction(
108
+ {
109
+ name: 'search.title',
110
+ icon: '$vcsSearch',
111
+ title: 'search.tooltip',
112
+ },
113
+ {
114
+ id: 'searchId',
115
+ component: SearchComponent,
116
+ state: { hideHeader: true },
117
+ slot: WindowSlot.DETACHED,
118
+ position: {
119
+ right: 0,
120
+ top: 0,
121
+ width: 440,
122
+ },
123
+ },
124
+ app.windowManager,
125
+ vcsAppSymbol,
126
+ );
127
+ destroyAction = action.destroy;
128
+ searchAction.value = reactive(action.action);
129
+ } else if (searchAction.value !== null) {
130
+ destroyAction();
131
+ destroyAction = () => {};
132
+ searchAction.value = null;
133
+ }
134
+ };
135
+ determineAction();
136
+ const listeners = [
137
+ app.search.added.addEventListener(determineAction),
138
+ app.search.removed.addEventListener(determineAction),
139
+ ];
140
+ const destroy = () => {
141
+ destroyAction();
142
+ listeners.forEach((cb) => { cb(); });
143
+ };
144
+
145
+ return { searchAction, destroy };
146
+ }
147
+
91
148
  /**
92
149
  * Creates an action which will toggle the overview map (opening & closing the window and activating/ deactivating the overview map).
93
150
  * @param {OverviewMap} overviewMap
@@ -260,3 +317,47 @@ export function createGoToViewpointAction(actionOptions, viewpoint, viewpointCol
260
317
  },
261
318
  };
262
319
  }
320
+
321
+ /**
322
+ * calculates and returns a viewpoint using feature's extent
323
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
324
+ * @returns {Viewpoint|null}
325
+ */
326
+ export function getViewpointFromFeature(feature) {
327
+ const extent = new Extent({
328
+ coordinates: feature.getGeometry()?.getExtent?.(),
329
+ projection: mercatorProjection,
330
+ });
331
+
332
+ if (!extent || !extent.isValid()) {
333
+ return null;
334
+ }
335
+ return Viewpoint.createViewpointFromExtent(extent);
336
+ }
337
+
338
+ /**
339
+ * Creates an action, which when clicked, zooms to the provided feature
340
+ * @param {ActionOptions} actionOptions
341
+ * @param {import("ol").Feature<import("ol/geom/Geometry").default>} feature
342
+ * @param {import("@vcmap/core").MapCollection} mapCollection
343
+ * @returns {VcsAction|null} returns null if the feature does not have a geometry with a valid extent
344
+ */
345
+ export function createZoomToFeatureAction(actionOptions, feature, mapCollection) {
346
+ check(actionOptions, {
347
+ name: String,
348
+ icon: [undefined, String],
349
+ title: [undefined, String],
350
+ });
351
+ check(feature, Feature);
352
+ check(mapCollection, MapCollection);
353
+
354
+ const viewpoint = getViewpointFromFeature(feature);
355
+
356
+ return {
357
+ title: 'search.zoomToFeatureAction',
358
+ ...actionOptions,
359
+ async callback() {
360
+ await mapCollection.activeMap.gotoViewpoint(viewpoint);
361
+ },
362
+ };
363
+ }
@@ -20,12 +20,21 @@
20
20
 
21
21
  <script>
22
22
  import { computed, inject, onUnmounted, ref } from 'vue';
23
+ import {
24
+ VChip, VList, VListItem, VListItemContent, VListItemIcon, VSheet,
25
+ } from 'vuetify/lib';
23
26
  import VcsSelect from '../components/form-inputs-controls/VcsSelect.vue';
24
27
 
25
28
  export default {
26
29
  name: 'StyleSelector',
27
30
  components: {
28
31
  VcsSelect,
32
+ VSheet,
33
+ VList,
34
+ VListItem,
35
+ VListItemIcon,
36
+ VChip,
37
+ VListItemContent,
29
38
  },
30
39
  props: {
31
40
  availableStyles: {