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

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 (105) 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 +26 -24
  6. package/config/dev.config.json +8 -0
  7. package/config/www.config.json +102 -17
  8. package/dist/assets/cesium.2e288a.js +137226 -0
  9. package/dist/assets/cesium.js +1 -1
  10. package/dist/assets/core.8014d3.js +14473 -0
  11. package/dist/assets/core.js +1 -1
  12. package/dist/assets/index.3f74fa92.js +1 -0
  13. package/dist/assets/ol.31c3a5.js +44279 -0
  14. package/dist/assets/ol.js +1 -1
  15. package/dist/assets/ui.36f84f.css +1 -0
  16. package/dist/assets/ui.36f84f.js +16101 -0
  17. package/dist/assets/ui.js +1 -1
  18. package/dist/assets/vue.a39c10.js +4675 -0
  19. package/dist/assets/vue.js +5 -2
  20. package/dist/assets/{vuetify.202322.css → vuetify.378637.css} +1 -1
  21. package/dist/assets/vuetify.378637.js +21019 -0
  22. package/dist/assets/vuetify.js +5 -2
  23. package/dist/index.html +1 -1
  24. package/index.js +4 -1
  25. package/package.json +10 -10
  26. package/plugins/@vcmap/pluginExample/index.js +14 -0
  27. package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +93 -67
  28. package/plugins/@vcmap/project-selector/ContextsListComponent.vue +8 -1
  29. package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +27 -1
  30. package/plugins/@vcmap/search-nominatim/LICENSE.md +14 -0
  31. package/plugins/@vcmap/search-nominatim/README.md +2 -0
  32. package/plugins/@vcmap/search-nominatim/config.json +4 -0
  33. package/plugins/@vcmap/search-nominatim/index.js +26 -0
  34. package/plugins/@vcmap/search-nominatim/nominatim.js +170 -0
  35. package/plugins/@vcmap/search-nominatim/package.json +43 -0
  36. package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +24 -0
  37. package/plugins/buttonExamples/ButtonExamples.vue +28 -1
  38. package/plugins/categoryTest/Categories.vue +16 -0
  39. package/plugins/categoryTest/Category.vue +30 -4
  40. package/plugins/example/mySuperComponent.vue +12 -1
  41. package/plugins/package.json +2 -1
  42. package/plugins/simple-graph/SimpleGraphComponent.vue +5 -11
  43. package/plugins/test/allIconsComponent.vue +16 -0
  44. package/plugins/test/editor.vue +3 -0
  45. package/plugins/test/emptyComponent.vue +3 -0
  46. package/plugins/test/vcsContent.vue +3 -0
  47. package/src/actions/actionHelper.js +103 -2
  48. package/src/actions/styleSelector.vue +9 -0
  49. package/src/application/VcsApp.vue +77 -9
  50. package/src/application/VcsAttributions.vue +63 -0
  51. package/src/application/VcsAttributionsFooter.vue +87 -0
  52. package/src/application/{Navbar.vue → VcsNavbar.vue} +35 -2
  53. package/src/application/VcsSettings.vue +4 -0
  54. package/src/application/attributionsHelper.js +150 -0
  55. package/src/application/vcsAppWrapper.vue +5 -1
  56. package/src/components/buttons/VcsActionButtonList.vue +8 -1
  57. package/src/components/buttons/VcsButton.vue +7 -1
  58. package/src/components/form-inputs-controls/VcsCheckbox.vue +7 -2
  59. package/src/components/form-inputs-controls/VcsColorPicker.vue +4 -0
  60. package/src/components/form-inputs-controls/VcsFormSection.vue +48 -2
  61. package/src/components/form-inputs-controls/VcsRadio.vue +7 -1
  62. package/src/components/form-inputs-controls/VcsSelect.vue +5 -1
  63. package/src/components/form-inputs-controls/VcsTextArea.vue +2 -0
  64. package/src/components/form-inputs-controls/VcsTextField.vue +6 -2
  65. package/src/components/lists/VcsActionList.vue +12 -1
  66. package/src/components/lists/VcsTreeview.vue +6 -1
  67. package/src/components/lists/VcsTreeviewLeaf.vue +5 -1
  68. package/src/components/lists/VcsTreeviewSearchbar.vue +5 -0
  69. package/src/components/notification/VcsTooltip.vue +14 -9
  70. package/src/components/tables/VcsTable.vue +117 -38
  71. package/src/featureInfo/AddressBalloonComponent.vue +17 -1
  72. package/src/featureInfo/BalloonComponent.vue +57 -23
  73. package/src/featureInfo/balloonFeatureInfoView.js +2 -2
  74. package/src/featureInfo/featureInfo.js +10 -2
  75. package/src/i18n/de.js +15 -0
  76. package/src/i18n/en.js +15 -0
  77. package/src/legend/legendHelper.js +18 -12
  78. package/src/legend/styleLegendItem.vue +20 -1
  79. package/src/legend/vcsLegend.vue +29 -3
  80. package/src/manager/toolbox/GroupToolboxComponent.vue +13 -1
  81. package/src/manager/toolbox/SelectToolboxComponent.vue +13 -1
  82. package/src/manager/toolbox/ToolboxManager.vue +3 -0
  83. package/src/manager/window/WindowComponent.vue +6 -0
  84. package/src/manager/window/WindowComponentHeader.vue +6 -1
  85. package/src/navigation/mapNavigation.vue +15 -36
  86. package/src/navigation/orientationToolsButton.vue +6 -1
  87. package/src/navigation/overviewMap.js +10 -39
  88. package/src/navigation/tiltSlider.vue +3 -0
  89. package/src/navigation/vcsCompass.vue +2 -0
  90. package/src/search/resultItem.vue +89 -0
  91. package/src/search/resultsComponent.vue +98 -0
  92. package/src/search/search.js +326 -0
  93. package/src/search/searchComponent.vue +90 -0
  94. package/src/styles/_typography.scss +3 -0
  95. package/src/styles/utils/_cursor.scss +4 -0
  96. package/src/styles/variables.scss +4 -1
  97. package/src/vcsUiApp.js +16 -0
  98. package/dist/assets/cesium.9489f8.js +0 -8699
  99. package/dist/assets/core.aa346a.js +0 -4
  100. package/dist/assets/index.3cd4fffa.js +0 -1
  101. package/dist/assets/ol.39651b.js +0 -439
  102. package/dist/assets/ui.15ef6a.css +0 -1
  103. package/dist/assets/ui.15ef6a.js +0 -71
  104. package/dist/assets/vue.cbe9d8.js +0 -9
  105. package/dist/assets/vuetify.202322.js +0 -148
@@ -0,0 +1,326 @@
1
+ import {
2
+ IndexedCollection,
3
+ markVolatile,
4
+ maxZIndex,
5
+ mercatorProjection,
6
+ VcsEvent,
7
+ vcsLayerName,
8
+ VectorLayer,
9
+ VectorStyleItem, Viewpoint,
10
+ } from '@vcmap/core';
11
+ import { shallowRef } from 'vue';
12
+ import { check } from '@vcsuite/check';
13
+ import { Icon } from 'ol/style.js';
14
+ import { getLogger } from '@vcsuite/logger';
15
+ import { vcsAppSymbol } from '../pluginHelper.js';
16
+ import { defaultPrimaryColor } from '../vuePlugins/vuetify.js';
17
+ import { getViewpointFromFeature } from '../actions/actionHelper.js';
18
+
19
+ /**
20
+ * A readonly rendering interface of a ResultItem.
21
+ * A ResultItem must provide either a feature, a clicked handler or both.
22
+ * @typedef {Object} ResultItem
23
+ * @property {string} title
24
+ * @property {string} [icon] An optional icon
25
+ * @property {Array<VcsAction>} [actions]
26
+ * @property {function():Promise<void>} [clicked] Obligatory, if no feature is provided. Can overwrite default zoom to feature behaviour.
27
+ * @property {import("ol").Feature|undefined} [feature] If a feature is provided, the feature is added to the result layer and search zooms to the layer's extent. Default clicked handler is zoom to feature, highlight feature and select feature, if feature has a FeatureInfoView.
28
+ */
29
+
30
+
31
+ /**
32
+ * @interface SearchImpl
33
+ * @property {string} name Name of the implementation. Must be the name of the plugin the SearchImpl is owned by
34
+ * @property {function(q:string):Array<ResultItem>} search
35
+ * @property {function(q:string):Array<string>} [suggest] // XXX currently not implemented in UI at Beta state
36
+ * @property{function():void} abort - should abort any ongoing requests to search or suggest without throwing an error
37
+ * @property {function():void} destroy
38
+ */
39
+
40
+ /**
41
+ * @param {string} color
42
+ * @returns {import("ol/style/Icon").Options}
43
+ */
44
+ function getPointResultIcon(color) {
45
+ return {
46
+ src: `data:image/svg+xml,%3Csvg xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns%23' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns%23' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' id='icon_24_poi' width='24' height='23.994' viewBox='0 0 24 23.994' sodipodi:docname='mapIcon.svg'%3E%3Cg id='Gruppe_1972' transform='translate(-571 -609.477)'%3E%3Cpath id='Pfad_773' d='M583,611a8.009,8.009,0,0,0-8,8c0,5.314,6.952,13.32,7.248,13.658a1,1,0,0,0,1.5,0c.3-.338,7.248-8.344,7.248-13.658A8.009,8.009,0,0,0,583,611Zm0,19.444c-2.18-2.685-6-8.09-6-11.444a6,6,0,0,1,12,0C589,622.354,585.18,627.759,583,630.444Z' fill='currentColor' /%3E%3Cpath id='Pfad_774' d='M583,615a4,4,0,1,0,4,4A4,4,0,0,0,583,615Zm0,6a2,2,0,1,1,2-2A2,2,0,0,1,583,621Z' fill='currentColor' /%3E%3C/g%3E%3Cpath fill='${encodeURIComponent(color)}' d='M 11.672998,20.526286 C 8.5115524,16.526958 6.4310003,12.714969 6.0702695,10.260963 6.0109099,9.8571482 6.0115821,9.1201807 6.0716855,8.7084104 6.4424582,6.1682348 8.3335069,4.1603103 10.828528,3.6575721 c 1.904966,-0.383844 3.881822,0.1903514 5.289639,1.5364231 0.993092,0.9495349 1.610829,2.1488769 1.810148,3.5144152 0.0601,0.4117703 0.06077,1.1487378 0.0014,1.5525526 -0.357076,2.429138 -2.337816,6.081898 -5.487559,10.119822 -0.224045,0.287223 -0.415188,0.530536 -0.424763,0.540696 -0.0096,0.01016 -0.16456,-0.167678 -0.344411,-0.395195 z m 0.990366,-7.047968 c 0.894914,-0.146674 1.762065,-0.627065 2.349286,-1.301476 0.86707,-0.995812 1.194989,-2.3427819 0.880571,-3.6170541 -0.379849,-1.5394474 -1.596396,-2.6842781 -3.173401,-2.9863277 -0.368703,-0.070619 -1.070937,-0.070619 -1.43964,0 C 9.7056173,5.875042 8.48604,7.0227247 8.1067793,8.5597879 7.8410265,9.6368274 8.0329903,10.787029 8.6317551,11.705317 c 0.5717674,0.876885 1.4205679,1.474277 2.4457369,1.721329 0.47704,0.114961 1.079877,0.134602 1.585872,0.05167 z' id='path1432' /%3E%3C/svg%3E`,
47
+ scale: 1,
48
+ color,
49
+ };
50
+ }
51
+
52
+ /**
53
+ * sets up result layer for displaying search results
54
+ * @param {VcsUiApp} app
55
+ * @returns {{ resultLayer: import("@vcmap/core").VectorLayer, destroy: (function(): void)}}
56
+ */
57
+ function setupSearchResultLayer(app) {
58
+ const resultLayer = new VectorLayer({
59
+ projection: mercatorProjection.toJSON(),
60
+ vectorProperties: {
61
+ altitudeMode: 'clampToGround',
62
+ classificationType: 'both',
63
+ },
64
+ properties: {
65
+ title: 'search.title',
66
+ },
67
+ zIndex: maxZIndex,
68
+ });
69
+ markVolatile(resultLayer);
70
+ app.layers.add(resultLayer);
71
+
72
+ const style = new VectorStyleItem({
73
+ image: getPointResultIcon(defaultPrimaryColor),
74
+ fill: {
75
+ color: 'rgba(237, 237, 237, 0.1)',
76
+ },
77
+ stroke: {
78
+ color: defaultPrimaryColor,
79
+ width: 5,
80
+ },
81
+ });
82
+ resultLayer.setStyle(style);
83
+
84
+ function setResultColor(color) {
85
+ style.stroke?.setColor(color);
86
+ style.image = new Icon(getPointResultIcon(color));
87
+ resultLayer.forceRedraw();
88
+ }
89
+
90
+ const listeners = [
91
+ app.uiConfig.added.addEventListener((item) => {
92
+ if (item.name === 'primaryColor') {
93
+ setResultColor(item.value);
94
+ }
95
+ }),
96
+ app.uiConfig.removed.addEventListener((item) => {
97
+ if (item.name === 'primaryColor') {
98
+ setResultColor(defaultPrimaryColor);
99
+ }
100
+ }),
101
+ ];
102
+
103
+ const destroy = () => {
104
+ resultLayer.destroy();
105
+ listeners.forEach(cb => cb());
106
+ };
107
+
108
+ return { resultLayer, destroy };
109
+ }
110
+
111
+ /**
112
+ * Symbol added to search implementations to specify the implementation's owner
113
+ * @type {symbol}
114
+ */
115
+ const searchImplOwnerSymbol = Symbol('featureInfoView');
116
+
117
+
118
+ /**
119
+ * Collection of SearchImpl
120
+ * @extends {IndexedCollection<SearchImpl<ResultItem>>}
121
+ */
122
+ class Search extends IndexedCollection {
123
+ /**
124
+ * @param {VcsUiApp} app
125
+ */
126
+ constructor(app) {
127
+ super();
128
+
129
+ /**
130
+ * @type {VcsUiApp}
131
+ * @private
132
+ */
133
+ this._app = app;
134
+
135
+ /**
136
+ * An event triggered every time the currentResults array changes,
137
+ * either by a new search providing the new results or
138
+ * on clearing, if the results array has not been empty already.
139
+ * @type {import("@vcmap/core").VcsEvent<Array<ResultItem>>}
140
+ * @private
141
+ */
142
+ this._resultsChanged = new VcsEvent();
143
+
144
+ /**
145
+ * @type {import("vue").Ref<Array<ResultItem>>}
146
+ * @private
147
+ */
148
+ this._currentResults = shallowRef([]);
149
+ const { resultLayer, destroy } = setupSearchResultLayer(app);
150
+ /**
151
+ * @type {import("@vcmap/core").VectorLayer}
152
+ * @private
153
+ */
154
+ this._resultLayer = resultLayer;
155
+ /**
156
+ * @type {function():void}
157
+ * @private
158
+ */
159
+ this._destroyResultLayer = destroy;
160
+ }
161
+
162
+ /**
163
+ * An event triggered every time the currentResults array changes,
164
+ * either by a new search providing the new results or
165
+ * on clearing, if the results array has not been empty already.
166
+ * @type {import("@vcmap/core").VcsEvent<Array<ResultItem>>}
167
+ * @readonly
168
+ */
169
+ get resultsChanged() {
170
+ return this._resultsChanged;
171
+ }
172
+
173
+ /**
174
+ * @type {import("vue").Ref<Array<ResultItem>>}
175
+ * @readonly
176
+ */
177
+ get currentResults() {
178
+ return this._currentResults;
179
+ }
180
+
181
+ /**
182
+ * @type {VectorLayer}
183
+ * @readonly
184
+ */
185
+ get resultLayer() {
186
+ return this._resultLayer;
187
+ }
188
+
189
+ /**
190
+ * @param {SearchImpl} item
191
+ * @param {string|symbol} owner pluginName or vcsAppSymbol
192
+ * @param {number=} index
193
+ */
194
+ add(item, owner, index) {
195
+ check(owner, [String, vcsAppSymbol]);
196
+ check(item.search, Function);
197
+ if (item.name !== owner) {
198
+ getLogger('Search').warning('SearchImplementations must be named as the plugin they are owned by.');
199
+ }
200
+ item[searchImplOwnerSymbol] = owner;
201
+ super.add(item, index);
202
+ }
203
+
204
+ /**
205
+ * removes all search implementations of a specific owner (plugin) and fires removed Events
206
+ * @param {string|vcsAppSymbol} owner
207
+ */
208
+ removeOwner(owner) {
209
+ this._array.forEach((impl) => {
210
+ if (impl[searchImplOwnerSymbol] === owner) {
211
+ super.remove(impl);
212
+ }
213
+ });
214
+ }
215
+
216
+ /**
217
+ * Get the results for a given query string.
218
+ * Available features are added to results layer and map is zoomed to all results (extent of result layer).
219
+ * Adds default clicked handler to result items with feature, which zooms to and highlights said feature. If feature has FeatureInfoView, feature is selected by featureInfo.
220
+ * @param {string} q
221
+ * @returns {Promise<Array<ResultItem>>}
222
+ */
223
+ async search(q) {
224
+ this.clearResults();
225
+ const promises = await Promise.allSettled([...this._array].map(impl => impl.search(q)));
226
+ const isAborted = promises.some(r => r.status === 'rejected' && r.reason?.name === 'AbortError');
227
+ if (!isAborted) {
228
+ const results = promises
229
+ .map((o) => {
230
+ if (o.status === 'rejected') {
231
+ getLogger('Search').warning(o.reason);
232
+ return [];
233
+ }
234
+ return o.value;
235
+ })
236
+ .flat();
237
+
238
+ this._currentResults.value = results
239
+ .filter(r => r.feature || r.clicked)
240
+ .map((item) => {
241
+ if (item.feature) {
242
+ this._resultLayer.addFeatures([item.feature]);
243
+ if (!item.clicked) {
244
+ const viewpoint = getViewpointFromFeature(item.feature);
245
+ item.clicked = () => {
246
+ this._app.maps.activeMap.gotoViewpoint(viewpoint);
247
+ return this._app.featureInfo.selectFeature(item.feature);
248
+ };
249
+ }
250
+ }
251
+ return item;
252
+ });
253
+ if (this._currentResults.value.length > 0) {
254
+ await this._resultLayer.activate();
255
+ const extent = this._resultLayer.getZoomToExtent();
256
+ const viewpoint = Viewpoint.createViewpointFromExtent(extent);
257
+ await this._app.maps.activeMap.gotoViewpoint(viewpoint);
258
+ this.resultsChanged.raiseEvent(this._currentResults.value.slice(0));
259
+ }
260
+ }
261
+ return this._currentResults.value;
262
+ }
263
+
264
+ /**
265
+ * Get the suggestions for a given query string
266
+ * @param {string} q
267
+ * @returns {Promise<Array<string>>}
268
+ */
269
+ async suggest(q) {
270
+ const promises = await Promise.allSettled([...this._array].map((impl) => {
271
+ if (impl.suggest) {
272
+ return impl.suggest(q);
273
+ }
274
+ return Promise.resolve([]);
275
+ }));
276
+ const isAborted = promises.some(r => r.status === 'rejected' && r.reason?.name === 'AbortError');
277
+ if (isAborted) {
278
+ return [];
279
+ }
280
+ const suggestions = promises
281
+ .map((o) => {
282
+ if (o.status === 'rejected') {
283
+ getLogger('Search').warning(o.reason);
284
+ return [];
285
+ }
286
+ return o.value;
287
+ })
288
+ .flat();
289
+ return suggestions;
290
+ }
291
+
292
+ /**
293
+ * Aborting any ongoing request
294
+ */
295
+ abort() {
296
+ [...this._array].forEach(impl => impl.abort?.());
297
+ }
298
+
299
+ /**
300
+ * Clears the results and aborts running request
301
+ */
302
+ clearResults() {
303
+ this.abort();
304
+ if (this._currentResults.value.length > 0) {
305
+ this._currentResults.value = [];
306
+ this.resultsChanged.raiseEvent(this._currentResults.value.slice(0));
307
+ }
308
+ this._resultLayer.removeAllFeatures();
309
+ this._resultLayer.deactivate();
310
+ if (this._app.featureInfo.selectedFeature?.[vcsLayerName] === this._resultLayer.name) {
311
+ this._app.featureInfo.clear();
312
+ }
313
+ }
314
+
315
+ /**
316
+ * @inheritDoc
317
+ */
318
+ destroy() {
319
+ [...this._array].forEach(impl => impl.destroy());
320
+ this.resultsChanged.destroy();
321
+ this._destroyResultLayer();
322
+ super.destroy();
323
+ }
324
+ }
325
+
326
+ export default Search;
@@ -0,0 +1,90 @@
1
+ <template>
2
+ <v-card>
3
+ <span class="d-flex justify-space-between align-center ma-1">
4
+ <v-icon
5
+ class="mx-2"
6
+ >
7
+ $vcsSearch
8
+ </v-icon>
9
+ <VcsTextField
10
+ class="font-size-14 d-inline-block user-select-none w-full mx-2"
11
+ autofocus
12
+ :loading="searching"
13
+ clearable
14
+ dense
15
+ :placeholder="$t('search.placeholder')"
16
+ v-model.trim="query"
17
+ @keydown.enter="search"
18
+ @keydown.esc="clear"
19
+ @input="reset"
20
+ />
21
+ </span>
22
+ <v-divider />
23
+ <ResultsComponent :query="query" :results="results" />
24
+ </v-card>
25
+ </template>
26
+
27
+ <style>
28
+
29
+ </style>
30
+
31
+ <script>
32
+ import { inject, onUnmounted, ref } from 'vue';
33
+ import { getLogger } from '@vcsuite/logger';
34
+ import { VCard, VDivider, VIcon } from 'vuetify/lib';
35
+ import VcsTextField from '../components/form-inputs-controls/VcsTextField.vue';
36
+ import ResultsComponent from './resultsComponent.vue';
37
+
38
+ export default {
39
+ components: {
40
+ ResultsComponent,
41
+ VcsTextField,
42
+ VCard,
43
+ VIcon,
44
+ VDivider,
45
+ },
46
+ setup() {
47
+ /** @type {VcsUiApp} */
48
+ const app = inject('vcsApp');
49
+ const searching = ref(false);
50
+ const query = ref(null);
51
+ const suggestions = ref([]);
52
+ const results = app.search.currentResults;
53
+
54
+ const reset = () => {
55
+ app.search.clearResults();
56
+ suggestions.value = [];
57
+ };
58
+
59
+ const clear = () => {
60
+ reset();
61
+ searching.value = false;
62
+ query.value = null;
63
+ };
64
+
65
+ const search = async () => {
66
+ reset();
67
+ searching.value = true;
68
+ try {
69
+ await app.search.search(query.value);
70
+ } catch (e) {
71
+ getLogger('Search').error(e);
72
+ }
73
+ searching.value = false;
74
+ };
75
+
76
+ onUnmounted(() => {
77
+ clear();
78
+ });
79
+
80
+ return {
81
+ query,
82
+ searching,
83
+ results,
84
+ reset,
85
+ clear,
86
+ search,
87
+ };
88
+ },
89
+ };
90
+ </script>
@@ -1,3 +1,5 @@
1
+ @use 'variables' as *;
2
+
1
3
  .v-application {
2
4
  h1,
3
5
  h2,
@@ -12,6 +14,7 @@
12
14
  .caption,
13
15
  .tooltip,
14
16
  p {
17
+ font-size: $font-size;
15
18
  &:not(.v-icon) {
16
19
  font-family: 'Titillium Web', sans-serif !important;
17
20
  }
@@ -6,6 +6,10 @@
6
6
  cursor: pointer;
7
7
  }
8
8
 
9
+ .cursor-auto {
10
+ cursor: auto;
11
+ }
12
+
9
13
  .cursor-not-allowed {
10
14
  cursor: not-allowed !important;
11
15
  }
@@ -71,8 +71,11 @@ $treeview-node-level-width: 16px;
71
71
  $treeview-node-margin: 4px;
72
72
  $treeview-node-height: 32px; // 48px !default;
73
73
 
74
- /** Expansion Panel */
74
+ /** Expansion Panel **/
75
75
  $expansion-panel-header-min-height: 32px; // 48px !default;
76
76
  $expansion-panel-active-header-min-height: 32px; // 64px !default;
77
77
  $expansion-panel-header-padding: 6px 0; // 16px 24px !default;
78
78
  $expansion-panel-content-padding: 0 0 4px; // 0 24px 16px !default;
79
+
80
+ /** Footer **/
81
+ $footer-padding: 0 8px; // 6px 16px !default;
package/src/vcsUiApp.js CHANGED
@@ -30,6 +30,7 @@ import FeatureInfo from './featureInfo/featureInfo.js';
30
30
  import UiConfig from './uiConfig.js';
31
31
  import { createEmptyState, getStateFromURL } from './state.js';
32
32
  import { version } from '../package.json';
33
+ import Search from './search/search.js';
33
34
 
34
35
  /**
35
36
  * @typedef {import("@vcmap/core").VcsAppConfig} VcsUiAppConfig
@@ -125,6 +126,7 @@ class VcsUiApp extends VcsApp {
125
126
  this._toolboxManager.removeOwner(plugin.name);
126
127
  this._categoryManager.removeOwner(plugin.name);
127
128
  this._contextMenuManager.removeOwner(plugin.name);
129
+ this._search.removeOwner(plugin.name);
128
130
  if (plugin.i18n) {
129
131
  this.i18n.addPluginMessages(plugin.name, plugin[contextIdSymbol], plugin.i18n);
130
132
  }
@@ -142,6 +144,7 @@ class VcsUiApp extends VcsApp {
142
144
  this._toolboxManager.removeOwner(plugin.name);
143
145
  this._categoryManager.removeOwner(plugin.name);
144
146
  this._contextMenuManager.removeOwner(plugin.name);
147
+ this._search.removeOwner(plugin.name);
145
148
  this.i18n.removePluginMessages(plugin.name, plugin[contextIdSymbol]);
146
149
  }),
147
150
  ];
@@ -210,6 +213,12 @@ class VcsUiApp extends VcsApp {
210
213
  */
211
214
  this._contextMenuManager = new ContextMenuManager(this);
212
215
 
216
+ /**
217
+ * @type {Search}
218
+ * @private
219
+ */
220
+ this._search = new Search(this);
221
+
213
222
  /**
214
223
  * @type {AppState}
215
224
  * @private
@@ -283,6 +292,12 @@ class VcsUiApp extends VcsApp {
283
292
  */
284
293
  get contextMenuManager() { return this._contextMenuManager; }
285
294
 
295
+ /**
296
+ * @type {Search}
297
+ * @readonly
298
+ */
299
+ get search() { return this._search; }
300
+
286
301
  /**
287
302
  * @type {UiConfig}
288
303
  * @readonly
@@ -447,6 +462,7 @@ class VcsUiApp extends VcsApp {
447
462
  destroyCollection(this._plugins);
448
463
  destroyCollection(this._contentTree);
449
464
  destroyCollection(this._i18n);
465
+ destroyCollection(this._search);
450
466
  this._contentTreeClassRegistry.destroy();
451
467
  this._featureInfo.destroy();
452
468
  this._uiConfig.destroy();