@vcmap/ui 6.1.0-rc.1 → 6.1.0-rc.3

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 (128) hide show
  1. package/config/base.config.json +6 -0
  2. package/config/clipping.config.json +384 -0
  3. package/config/cluster.config.json +106 -0
  4. package/config/concepts-show-case.config.json +4 -0
  5. package/config/projects.config.json +5 -2
  6. package/dist/assets/{cesium-11e5bbc6.js → cesium-87d5e72d.js} +438 -432
  7. package/dist/assets/cesium.js +1 -1
  8. package/dist/assets/{core-9d0cfec3.js → core-72f9f393.js} +4907 -4514
  9. package/dist/assets/core.js +1 -1
  10. package/dist/assets/{ol-0d0ebb27.js → ol-e468ba43.js} +23518 -22404
  11. package/dist/assets/ol.js +1 -1
  12. package/dist/assets/ui-73257b15.css +1 -0
  13. package/dist/assets/{ui-08446666.js → ui-73257b15.js} +13703 -12977
  14. package/dist/assets/ui.js +1 -1
  15. package/dist/assets/vue.js +1 -1
  16. package/dist/assets/{vuetify-67025c41.css → vuetify-2437380c.css} +2 -2
  17. package/dist/assets/{vuetify-67025c41.js → vuetify-2437380c.js} +8024 -7634
  18. package/dist/assets/vuetify.js +1 -1
  19. package/index.d.ts +40 -19
  20. package/index.js +36 -6
  21. package/lib/olLib.js +25 -3
  22. package/package.json +6 -6
  23. package/plugins/@vcmap-show-case/callback-tester/README.md +3 -0
  24. package/plugins/@vcmap-show-case/callback-tester/package.json +5 -0
  25. package/plugins/@vcmap-show-case/callback-tester/src/CallbackTester.vue +62 -0
  26. package/plugins/@vcmap-show-case/callback-tester/src/index.js +48 -0
  27. package/plugins/@vcmap-show-case/form-inputs-example/src/FormInputsExample.vue +1 -0
  28. package/src/actions/actionHelper.d.ts +1 -0
  29. package/src/actions/actionHelper.js +70 -19
  30. package/src/application/VcsApp.vue +83 -50
  31. package/src/application/VcsApp.vue.d.ts +28 -2
  32. package/src/application/VcsContainer.vue +5 -3
  33. package/src/application/VcsContainer.vue.d.ts +14 -0
  34. package/src/application/VcsNavbar.vue +10 -6
  35. package/src/application/VcsNavbar.vue.d.ts +2 -0
  36. package/src/application/VcsObliqueFooter.vue +9 -3
  37. package/src/application/VcsSplashScreen.vue +37 -0
  38. package/src/application/VcsSplashScreen.vue.d.ts +6 -0
  39. package/src/application/positionDisplayInteraction.js +1 -1
  40. package/src/callback/activateClippingPolygonCallback.d.ts +29 -0
  41. package/src/callback/activateClippingPolygonCallback.js +54 -0
  42. package/src/callback/closeSplashScreenCallback.d.ts +8 -0
  43. package/src/callback/closeSplashScreenCallback.js +33 -0
  44. package/src/callback/deactivateClippingPolygonCallback.d.ts +29 -0
  45. package/src/callback/deactivateClippingPolygonCallback.js +54 -0
  46. package/src/callback/openSplashScreenCallback.d.ts +8 -0
  47. package/src/callback/openSplashScreenCallback.js +35 -0
  48. package/src/callback/toggleNavbarButtonCallback.d.ts +36 -0
  49. package/src/callback/toggleNavbarButtonCallback.js +62 -0
  50. package/src/components/buttons/VcsActionButtonList.vue +6 -4
  51. package/src/components/buttons/VcsToolButton.vue +0 -1
  52. package/src/components/form-inputs-controls/VcsDatePicker.vue +7 -1
  53. package/src/components/form-inputs-controls/VcsDatePicker.vue.d.ts +9 -0
  54. package/src/components/form-inputs-controls/VcsSelect.vue +1 -1
  55. package/src/components/form-inputs-controls/VcsTextArea.vue +13 -8
  56. package/src/components/form-output/markdownHelper.d.ts +0 -25
  57. package/src/components/form-output/markdownHelper.js +1 -386
  58. package/src/components/import/VcsImportComponent.vue +2 -0
  59. package/src/components/lists/VcsGroupedList.vue +178 -0
  60. package/src/components/lists/VcsGroupedList.vue.d.ts +17 -0
  61. package/src/components/lists/VcsList.vue +144 -394
  62. package/src/components/lists/VcsList.vue.d.ts +38 -159
  63. package/src/components/lists/VcsTreeNode.vue +18 -11
  64. package/src/components/lists/VcsTreeview.vue +27 -20
  65. package/src/components/lists/VcsTreeview.vue.d.ts +18 -1
  66. package/src/components/lists/listHelper.d.ts +87 -0
  67. package/src/components/lists/listHelper.js +348 -0
  68. package/src/components/section/VcsFormSection.vue +7 -2
  69. package/src/components/section/VcsFormSection.vue.d.ts +9 -0
  70. package/src/components/tables/VcsDataTable.vue +14 -3
  71. package/src/components/tables/VcsDataTable.vue.d.ts +9 -0
  72. package/src/components/vector-properties/VcsVectorPropertiesComponent.vue.d.ts +1 -1
  73. package/src/contentTree/LayerTree.vue +2 -1
  74. package/src/contentTree/LayerTree.vue.d.ts +2 -0
  75. package/src/contentTree/contentTreeCollection.d.ts +1 -0
  76. package/src/contentTree/contentTreeCollection.js +7 -3
  77. package/src/contentTree/contentTreeItem.js +4 -2
  78. package/src/contentTree/groupContentTreeItem.js +5 -3
  79. package/src/featureInfo/ClusterFeatureComponent.vue +58 -0
  80. package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +6 -0
  81. package/src/featureInfo/abstractFeatureInfoView.js +1 -2
  82. package/src/featureInfo/featureInfo.d.ts +87 -1
  83. package/src/featureInfo/featureInfo.js +342 -34
  84. package/src/featureInfo/featureInfoInteraction.js +18 -3
  85. package/src/featureInfo/iframeFeatureInfoView.js +1 -1
  86. package/src/featureInfo/markdownBalloonFeatureInfoView.js +2 -4
  87. package/src/featureInfo/markdownFeatureInfoView.js +1 -1
  88. package/src/i18n/de.d.ts +17 -4
  89. package/src/i18n/de.js +7 -0
  90. package/src/i18n/en.d.ts +17 -4
  91. package/src/i18n/en.js +7 -0
  92. package/src/legend/VcsLegend.vue +1 -1
  93. package/src/legend/legendHelper.d.ts +1 -1
  94. package/src/legend/legendHelper.js +52 -9
  95. package/src/localStorage.d.ts +21 -0
  96. package/src/localStorage.js +51 -0
  97. package/src/manager/collectionManager/CollectionComponent.vue +1 -1
  98. package/src/manager/collectionManager/CollectionComponentContent.vue +2 -3
  99. package/src/manager/collectionManager/CollectionComponentList.vue +2 -3
  100. package/src/manager/collectionManager/CollectionComponentStandalone.vue +1 -1
  101. package/src/manager/navbarManager.js +9 -4
  102. package/src/manager/toolbox/ToolboxManagerComponent.vue +14 -12
  103. package/src/manager/toolbox/ToolboxManagerComponent.vue.d.ts +13 -2
  104. package/src/manager/toolbox/toolboxManager.d.ts +5 -0
  105. package/src/manager/toolbox/toolboxManager.js +7 -1
  106. package/src/manager/window/WindowComponent.vue +10 -0
  107. package/src/manager/window/WindowComponent.vue.d.ts +1 -0
  108. package/src/manager/window/WindowManager.vue +14 -4
  109. package/src/manager/window/WindowManager.vue.d.ts +1 -0
  110. package/src/manager/window/windowHelper.d.ts +7 -3
  111. package/src/manager/window/windowHelper.js +30 -10
  112. package/src/navigation/MapNavigation.vue +5 -5
  113. package/src/navigation/MapNavigation.vue.d.ts +1 -1
  114. package/src/navigation/overviewMap.d.ts +7 -0
  115. package/src/navigation/overviewMap.js +18 -4
  116. package/src/pluginHelper.d.ts +7 -0
  117. package/src/pluginHelper.js +18 -4
  118. package/src/search/ResultItem.vue.d.ts +1 -1
  119. package/src/search/markText.d.ts +1 -1
  120. package/src/search/markText.js +4 -4
  121. package/src/search/search.js +1 -1
  122. package/src/state.d.ts +4 -2
  123. package/src/state.js +54 -31
  124. package/src/uiConfig.d.ts +36 -0
  125. package/src/uiConfig.js +17 -1
  126. package/src/vcsUiApp.js +7 -11
  127. package/dist/assets/ui-08446666.css +0 -1
  128. /package/dist/assets/{vue-2f81c7f8.js → vue-ff37ea23.js} +0 -0
@@ -2,6 +2,8 @@ import {
2
2
  AbstractInteraction,
3
3
  EventType,
4
4
  ModificationKeyType,
5
+ vectorClusterGroupName,
6
+ isProvidedClusterFeature,
5
7
  } from '@vcmap/core';
6
8
 
7
9
  /**
@@ -28,9 +30,22 @@ class FeatureInfoInteraction extends AbstractInteraction {
28
30
  */
29
31
  async pipe(event) {
30
32
  if (event.feature) {
31
- if (
33
+ const featureId = event.feature.getId();
34
+ const isClusterFeature = !!(
35
+ event.feature[vectorClusterGroupName] ||
36
+ event.feature[isProvidedClusterFeature]
37
+ );
38
+ if (isClusterFeature) {
39
+ if (
40
+ !this._featureInfo.selectedClusterFeature ||
41
+ featureId !== this._featureInfo.selectedClusterFeatureId
42
+ ) {
43
+ event.stopPropagation = true;
44
+ await this._featureInfo.selectClusterFeature(event.feature);
45
+ }
46
+ } else if (
32
47
  !this._featureInfo.selectedFeature ||
33
- event.feature.getId() !== this._featureInfo.selectedFeatureId
48
+ featureId !== this._featureInfo.selectedFeatureId
34
49
  ) {
35
50
  event.stopPropagation = true;
36
51
  await this._featureInfo.selectFeature(event.feature, event.position, [
@@ -39,7 +54,7 @@ class FeatureInfoInteraction extends AbstractInteraction {
39
54
  ]);
40
55
  }
41
56
  } else {
42
- await this._featureInfo.clear();
57
+ await this._featureInfo.clearSelection();
43
58
  }
44
59
  return event;
45
60
  }
@@ -1,4 +1,4 @@
1
- import { renderTemplate } from '../components/form-output/markdownHelper.js';
1
+ import { renderTemplate } from '@vcmap/core';
2
2
  import AbstractFeatureInfoView from './abstractFeatureInfoView.js';
3
3
  import IframeComponent from './IframeComponent.vue';
4
4
 
@@ -1,7 +1,5 @@
1
- import {
2
- parseAndSanitizeMarkdown,
3
- renderTemplate,
4
- } from '../components/form-output/markdownHelper.js';
1
+ import { renderTemplate } from '@vcmap/core';
2
+ import { parseAndSanitizeMarkdown } from '../components/form-output/markdownHelper.js';
5
3
  import BalloonFeatureInfoView from './balloonFeatureInfoView.js';
6
4
  import MarkdownBalloonComponent from './MarkdownBalloonComponent.vue';
7
5
 
@@ -1,4 +1,4 @@
1
- import { renderTemplate } from '../components/form-output/markdownHelper.js';
1
+ import { renderTemplate } from '@vcmap/core';
2
2
  import AbstractFeatureInfoView from './abstractFeatureInfoView.js';
3
3
  import VcsMarkdown from '../components/form-output/VcsMarkdown.vue';
4
4
 
package/src/i18n/de.d.ts CHANGED
@@ -73,6 +73,11 @@ declare namespace messages {
73
73
  counter: string;
74
74
  counterSize: string;
75
75
  };
76
+ fileUpload: {
77
+ title: string;
78
+ divider: string;
79
+ browse: string;
80
+ };
76
81
  timePicker: {
77
82
  am: string;
78
83
  pm: string;
@@ -278,6 +283,7 @@ declare namespace messages {
278
283
  export { name_2 as name };
279
284
  export let checkBoxText: string;
280
285
  export let buttonTitle: string;
286
+ export let dontShowAgain: string;
281
287
  }
282
288
  export namespace customScreen {
283
289
  let name_3: string;
@@ -457,14 +463,21 @@ declare namespace messages {
457
463
  export namespace featureInfo {
458
464
  let activateToolTitle: string;
459
465
  let deactivateToolTitle: string;
466
+ namespace cluster {
467
+ export let headerTitle: string;
468
+ export let expand: string;
469
+ export let collapse: string;
470
+ let empty_2: string;
471
+ export { empty_2 as empty };
472
+ }
460
473
  }
461
474
  export namespace legend {
462
475
  let title_17: string;
463
476
  export { title_17 as title };
464
477
  let tooltip_5: string;
465
478
  export { tooltip_5 as tooltip };
466
- let empty_2: string;
467
- export { empty_2 as empty };
479
+ let empty_3: string;
480
+ export { empty_3 as empty };
468
481
  export let openInNew: string;
469
482
  export let defaultLabelText: string;
470
483
  }
@@ -495,8 +508,8 @@ declare namespace messages {
495
508
  export { title_21 as title };
496
509
  let tooltip_7: string;
497
510
  export { tooltip_7 as tooltip };
498
- let empty_3: string;
499
- export { empty_3 as empty };
511
+ let empty_4: string;
512
+ export { empty_4 as empty };
500
513
  }
501
514
  export namespace imprint {
502
515
  let title_22: string;
package/src/i18n/de.js CHANGED
@@ -172,6 +172,7 @@ const messages = {
172
172
  checkBoxText:
173
173
  'Bitte akzeptieren sie die [Bedingungen](https://vc.systems/) um Fortzufahren',
174
174
  buttonTitle: 'Weiter',
175
+ dontShowAgain: 'Diese Nachricht nicht erneut anzeigen',
175
176
  },
176
177
  customScreen: {
177
178
  name: 'Benutzerdefinierter Screen',
@@ -325,6 +326,12 @@ const messages = {
325
326
  featureInfo: {
326
327
  activateToolTitle: 'Informationen abfragen',
327
328
  deactivateToolTitle: 'Informationen abfragen',
329
+ cluster: {
330
+ headerTitle: 'Gruppeninformationen',
331
+ expand: 'Informationsliste anzeigen',
332
+ collapse: 'Informationsliste minimieren',
333
+ empty: 'Keine Informationen verfügbar',
334
+ },
328
335
  },
329
336
  legend: {
330
337
  title: 'Legende',
package/src/i18n/en.d.ts CHANGED
@@ -73,6 +73,11 @@ declare namespace messages {
73
73
  counter: string;
74
74
  counterSize: string;
75
75
  };
76
+ fileUpload: {
77
+ title: string;
78
+ divider: string;
79
+ browse: string;
80
+ };
76
81
  timePicker: {
77
82
  am: string;
78
83
  pm: string;
@@ -278,6 +283,7 @@ declare namespace messages {
278
283
  export { name_2 as name };
279
284
  export let checkBoxText: string;
280
285
  export let buttonTitle: string;
286
+ export let dontShowAgain: string;
281
287
  }
282
288
  export namespace customScreen {
283
289
  let name_3: string;
@@ -457,14 +463,21 @@ declare namespace messages {
457
463
  export namespace featureInfo {
458
464
  let activateToolTitle: string;
459
465
  let deactivateToolTitle: string;
466
+ namespace cluster {
467
+ export let headerTitle: string;
468
+ export let expand: string;
469
+ export let collapse: string;
470
+ let empty_2: string;
471
+ export { empty_2 as empty };
472
+ }
460
473
  }
461
474
  export namespace legend {
462
475
  let title_17: string;
463
476
  export { title_17 as title };
464
477
  let tooltip_5: string;
465
478
  export { tooltip_5 as tooltip };
466
- let empty_2: string;
467
- export { empty_2 as empty };
479
+ let empty_3: string;
480
+ export { empty_3 as empty };
468
481
  export let openInNew: string;
469
482
  export let defaultLabelText: string;
470
483
  }
@@ -495,8 +508,8 @@ declare namespace messages {
495
508
  export { title_21 as title };
496
509
  let tooltip_7: string;
497
510
  export { tooltip_7 as tooltip };
498
- let empty_3: string;
499
- export { empty_3 as empty };
511
+ let empty_4: string;
512
+ export { empty_4 as empty };
500
513
  }
501
514
  export namespace imprint {
502
515
  let title_22: string;
package/src/i18n/en.js CHANGED
@@ -172,6 +172,7 @@ const messages = {
172
172
  checkBoxText:
173
173
  'Please accept the [Conditions](https://vc.systems/) to continue',
174
174
  buttonTitle: 'Continue',
175
+ dontShowAgain: "Don't show this message again",
175
176
  },
176
177
  customScreen: {
177
178
  name: 'Custom Screen',
@@ -325,6 +326,12 @@ const messages = {
325
326
  featureInfo: {
326
327
  activateToolTitle: 'Query information',
327
328
  deactivateToolTitle: 'Query information',
329
+ cluster: {
330
+ headerTitle: 'Group information',
331
+ expand: 'Show information list',
332
+ collapse: 'Collapse information list',
333
+ empty: 'No information available',
334
+ },
328
335
  },
329
336
  legend: {
330
337
  title: 'Legend',
@@ -19,7 +19,7 @@
19
19
  <div v-if="item.type === LegendType.Image">
20
20
  <img
21
21
  :src="$st(item.src)"
22
- :alt="item.src"
22
+ :alt="$st(item.src)"
23
23
  class="legend-image"
24
24
  :title="item.tooltip"
25
25
  />
@@ -70,7 +70,7 @@ export function getImageSrcFromShape(image: import("ol/style/Image.js").Options)
70
70
  * @param {Array<LegendItem>} legend
71
71
  * @returns {LegendEntry}
72
72
  */
73
- export function createLayerLegendEntry(key: string, title: string, legend: Array<LegendItem>): LegendEntry;
73
+ export function createLegendEntry(key: string, title: string, legend: Array<LegendItem>): LegendEntry;
74
74
  /**
75
75
  *
76
76
  * @param {import("../vcsUiApp.js").default} app
@@ -117,7 +117,7 @@ export function getImageSrcFromShape(image) {
117
117
  * @param {Array<LegendItem>} legend
118
118
  * @returns {LegendEntry}
119
119
  */
120
- export function createLayerLegendEntry(key, title, legend) {
120
+ export function createLegendEntry(key, title, legend) {
121
121
  const actions = [];
122
122
  legend.forEach((item) => {
123
123
  // XXX only one popout button allowed. Rethink if use case for multiple popout buttons comes up.
@@ -176,7 +176,7 @@ export function getLegendEntries(app) {
176
176
  const legend =
177
177
  layer.style?.properties?.legend ?? layer.properties?.legend;
178
178
  if (legend) {
179
- const legendEntry = createLayerLegendEntry(key, title, legend);
179
+ const legendEntry = createLegendEntry(key, title, legend);
180
180
  entries.unshift(legendEntry);
181
181
  }
182
182
  if (layer.styleChanged) {
@@ -187,17 +187,60 @@ export function getLegendEntries(app) {
187
187
  }
188
188
  }
189
189
 
190
- const destroyMapListener = app.maps.mapActivated.addEventListener(() =>
191
- [...app.layers].forEach(syncLayerLegendEntries),
192
- );
190
+ /**
191
+ * @param {import("@vcmap/core").VectorClusterGroup} group
192
+ */
193
+ function removeEntryForGroup(group) {
194
+ const groupName = group.name;
195
+ const entryIndex = entries.findIndex(({ key }) => key === groupName);
196
+ if (entryIndex >= 0) {
197
+ entries.splice(entryIndex, 1);
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Handles addition or removal of VectorClusterGroups
203
+ * @param {import("@vcmap/core").Layer[]} layers
204
+ */
205
+ function syncVectorClusterGroups(layers) {
206
+ [...app.vectorClusterGroups].forEach(removeEntryForGroup);
207
+ const vectorClusterGroups = layers
208
+ .filter((layer) => layer.active && layer.isSupported)
209
+ .map((layer) => layer.vectorClusterGroup);
210
+ const uniqueVectorClusterGroups = [...new Set(vectorClusterGroups)];
211
+ uniqueVectorClusterGroups.forEach((groupName) => {
212
+ const group = app.vectorClusterGroups.getByKey(groupName);
213
+ if (group?.properties?.legend) {
214
+ const title = group.properties.title || group.name;
215
+ const { legend } = group.properties;
216
+ if (!entries.some(({ key }) => key === group.name)) {
217
+ const legendEntry = createLegendEntry(group.name, title, legend);
218
+ entries.unshift(legendEntry);
219
+ }
220
+ }
221
+ });
222
+ }
223
+
224
+ const destroyMapListener = app.maps.mapActivated.addEventListener(() => {
225
+ [...app.layers].forEach(syncLayerLegendEntries);
226
+ syncVectorClusterGroups([...app.layers]);
227
+ });
193
228
 
194
229
  const destroyChangedListener = app.layers.stateChanged.addEventListener(
195
- syncLayerLegendEntries,
230
+ (l) => {
231
+ syncLayerLegendEntries(l);
232
+ syncVectorClusterGroups([...app.layers]);
233
+ },
196
234
  );
197
- const destroyRemovedListener =
198
- app.layers.removed.addEventListener(removeEntryForLayer);
235
+ const destroyRemovedListener = app.layers.removed.addEventListener((l) => {
236
+ removeEntryForLayer(l);
237
+ syncVectorClusterGroups([...app.layers]);
238
+ });
199
239
 
200
- [...app.layers].forEach(syncLayerLegendEntries);
240
+ [...app.layers].forEach((l) => {
241
+ syncLayerLegendEntries(l);
242
+ });
243
+ syncVectorClusterGroups([...app.layers]);
201
244
 
202
245
  const destroy = () => {
203
246
  destroyMapListener();
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @param {string} prefix The prefix to append to the key.
3
+ * @param {string} key The key to obtain the value.
4
+ * @returns {string|null} The value of the passed key, or null.
5
+ */
6
+ export function getFromLocalStorage(prefix: string, key: string): string | null;
7
+ /**
8
+ * Associates a value with the key in the LocalStorage.
9
+ * @param {string} prefix The prefix to append to the key.
10
+ * @param {string} key The key whose value must be defined.
11
+ * @param {string} value The value to associate with the key.
12
+ */
13
+ export function setToLocalStorage(prefix: string, key: string, value: string): void;
14
+ /**
15
+ * Removes a key from the LocalStorage.
16
+ * @param {string} prefix The prefix to append to the key.
17
+ * @param {string} key The key to remove.
18
+ */
19
+ export function removeFromLocalStorage(prefix: string, key: string): void;
20
+ /** The key, to which must be appended `_{moduleId}`, used in the LocalStorage to hide the SplashScreen when user checked the 'Remember me' checkbox. The value must be the hashed config. */
21
+ export const hideSplashScreenKey: "hideSplashScreen";
@@ -0,0 +1,51 @@
1
+ import { getLogger } from '@vcsuite/logger';
2
+
3
+ /** The key, to which must be appended `_{moduleId}`, used in the LocalStorage to hide the SplashScreen when user checked the 'Remember me' checkbox. The value must be the hashed config. */
4
+ export const hideSplashScreenKey = 'hideSplashScreen';
5
+
6
+ /**
7
+ * @param {string} prefix The prefix to append to the key.
8
+ * @param {string} key The key to obtain the value.
9
+ * @returns {string|null} The value of the passed key, or null.
10
+ */
11
+ export function getFromLocalStorage(prefix, key) {
12
+ try {
13
+ return localStorage.getItem(`${prefix}_${key}`);
14
+ } catch (error) {
15
+ getLogger().warning(
16
+ `An error occured while getting the key "${key}": ${error}`,
17
+ );
18
+ return null;
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Associates a value with the key in the LocalStorage.
24
+ * @param {string} prefix The prefix to append to the key.
25
+ * @param {string} key The key whose value must be defined.
26
+ * @param {string} value The value to associate with the key.
27
+ */
28
+ export function setToLocalStorage(prefix, key, value) {
29
+ try {
30
+ localStorage.setItem(`${prefix}_${key}`, value);
31
+ } catch (error) {
32
+ getLogger().warning(
33
+ `An error occured while setting the key "${key}": ${error}`,
34
+ );
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Removes a key from the LocalStorage.
40
+ * @param {string} prefix The prefix to append to the key.
41
+ * @param {string} key The key to remove.
42
+ */
43
+ export function removeFromLocalStorage(prefix, key) {
44
+ try {
45
+ localStorage.removeItem(`${prefix}_${key}`);
46
+ } catch (error) {
47
+ getLogger().warning(
48
+ `An error occured while removing the key "${key}": ${error}`,
49
+ );
50
+ }
51
+ }
@@ -19,8 +19,8 @@
19
19
  <script>
20
20
  import { computed, inject } from 'vue';
21
21
  import VcsExpansionPanel from '../../components/section/VcsExpansionPanel.vue';
22
- import { createSelectionActions } from '../../components/lists/VcsList.vue';
23
22
  import CollectionComponentContent from './CollectionComponentContent.vue';
23
+ import { createSelectionActions } from '../../components/lists/listHelper.js';
24
24
 
25
25
  /**
26
26
  * @typedef {Object} FormSectionOptions
@@ -23,9 +23,8 @@
23
23
  <script>
24
24
  import { computed, inject } from 'vue';
25
25
  import { VSheet, VContainer } from 'vuetify/components';
26
- import VcsList, {
27
- createSelectionActions,
28
- } from '../../components/lists/VcsList.vue';
26
+ import { createSelectionActions } from '../../components/lists/listHelper.js';
27
+ import VcsList from '../../components/lists/VcsList.vue';
29
28
  import VcsButton from '../../components/buttons/VcsButton.vue';
30
29
  import { moveItem } from './CollectionComponentList.vue';
31
30
 
@@ -38,9 +38,8 @@
38
38
  import { computed, inject } from 'vue';
39
39
  import { IndexedCollection } from '@vcmap/core';
40
40
  import { VSheet } from 'vuetify/components';
41
- import VcsList, {
42
- createSelectionActions,
43
- } from '../../components/lists/VcsList.vue';
41
+ import { createSelectionActions } from '../../components/lists/listHelper.js';
42
+ import VcsList from '../../components/lists/VcsList.vue';
44
43
  import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
45
44
  import VcsButton from '../../components/buttons/VcsButton.vue';
46
45
 
@@ -17,8 +17,8 @@
17
17
 
18
18
  <script>
19
19
  import { computed, getCurrentInstance, inject, ref } from 'vue';
20
+ import { createSelectionActions } from '../../components/lists/listHelper.js';
20
21
  import VcsFormSection from '../../components/section/VcsFormSection.vue';
21
- import { createSelectionActions } from '../../components/lists/VcsList.vue';
22
22
  import CollectionComponentList from './CollectionComponentList.vue';
23
23
  import CollectionComponentContent from './CollectionComponentContent.vue';
24
24
 
@@ -101,15 +101,20 @@ class NavbarManager extends ButtonManager {
101
101
  * @param {string} id
102
102
  * @param {boolean} [active]
103
103
  */
104
- toggle(id, active = undefined) {
104
+ toggle(id, active) {
105
105
  check(id, String);
106
106
  if (this.has(id)) {
107
107
  const { action } = this.get(id);
108
- if (active !== undefined) {
109
- if (action?.active !== active) {
108
+ if (action.disabled) {
109
+ return;
110
+ }
111
+
112
+ if (active != null) {
113
+ const isActionActive = action.active && !action.background;
114
+ if (isActionActive !== active) {
110
115
  action.callback();
111
116
  }
112
- } else if (action) {
117
+ } else {
113
118
  action.callback();
114
119
  }
115
120
  }
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <v-toolbar
3
- v-if="toolboxOpen && orderedGroups.length > 0 && mdAndUp"
3
+ v-if="toolboxOpen && orderedGroups.length > 0 && smAndUp"
4
4
  class="vcs-toolbox mx-auto elevation-4 opacity-80 toolbox-manager-component"
5
5
  :class="{
6
6
  'rounded-b': !open,
@@ -90,6 +90,8 @@
90
90
  * @property {function(number):void} [selectCb]
91
91
  */
92
92
 
93
+ export const toolboxComponentId = 'toolbox';
94
+
93
95
  /**
94
96
  * @description ToolboxManager component rendering toolbox different kind of Toolbox buttons:
95
97
  * - Single toggle button
@@ -125,7 +127,7 @@
125
127
  });
126
128
 
127
129
  const zIndex = app.windowManager.addExternalIdToZIndex(
128
- 'toolbox',
130
+ toolboxComponentId,
129
131
  vcsAppSymbol,
130
132
  );
131
133
 
@@ -150,7 +152,7 @@
150
152
  .filter(filterFunc),
151
153
  );
152
154
 
153
- const toolboxOpen = ref(true);
155
+ const toolboxOpen = app.toolboxManager.open;
154
156
  const toolboxToggleAction = {
155
157
  name: 'toolboxToggleAction',
156
158
  icon: '$vcsTools',
@@ -164,10 +166,10 @@
164
166
 
165
167
  function handleToolboxButton() {
166
168
  if (orderedGroups.value.length > 0) {
167
- if (!app.navbarManager.has('toolbox')) {
169
+ if (!app.navbarManager.has(toolboxComponentId)) {
168
170
  app.navbarManager.add(
169
171
  {
170
- id: 'toolbox',
172
+ id: toolboxComponentId,
171
173
  action: toolboxToggleAction,
172
174
  },
173
175
  vcsAppSymbol,
@@ -175,7 +177,7 @@
175
177
  );
176
178
  }
177
179
  } else {
178
- app.navbarManager.remove('toolbox');
180
+ app.navbarManager.remove(toolboxComponentId);
179
181
  }
180
182
  }
181
183
  handleToolboxButton();
@@ -184,28 +186,28 @@
184
186
 
185
187
  onUnmounted(() => {
186
188
  nameChangeListener();
187
- app.windowManager.removeExternalIdFromZIndex('toolbox');
188
- app.navbarManager.remove('toolbox');
189
+ app.windowManager.removeExternalIdFromZIndex(toolboxComponentId);
190
+ app.navbarManager.remove(toolboxComponentId);
189
191
  });
190
192
 
191
193
  watch(toolboxOpen, () => {
192
194
  if (toolboxOpen.value) {
193
- app.windowManager.bringWindowToTop('toolbox');
195
+ app.windowManager.bringWindowToTop(toolboxComponentId);
194
196
  }
195
197
  });
196
198
 
197
199
  const open = ref(false);
198
200
  const bringToTop = () => {
199
- app.windowManager.bringWindowToTop('toolbox');
201
+ app.windowManager.bringWindowToTop(toolboxComponentId);
200
202
  };
201
203
 
202
- const { mdAndUp } = useDisplay();
204
+ const { smAndUp } = useDisplay();
203
205
  const fontSize = useFontSize();
204
206
  const toolboxHeight = computed(() => {
205
207
  return fontSize.value * 3 + 1;
206
208
  });
207
209
  return {
208
- mdAndUp,
210
+ smAndUp,
209
211
  toolboxOpen,
210
212
  orderedGroups,
211
213
  zIndex,
@@ -1,6 +1,17 @@
1
+ /**
2
+ * @typedef {Object} ToolboxButtonGroup
3
+ * @property {string} id
4
+ * @property {string} type
5
+ * @property {string} icon
6
+ * @property {string} title
7
+ * @property {Array<import("../buttonManager.js").ButtonComponent>} buttons
8
+ * @property {string} [selected]
9
+ * @property {function(number):void} [selectCb]
10
+ */
11
+ export const toolboxComponentId: "toolbox";
1
12
  declare const _default: import("vue").DefineComponent<{}, {
2
- mdAndUp: import("vue").Ref<boolean>;
3
- toolboxOpen: import("vue").Ref<boolean>;
13
+ smAndUp: import("vue").Ref<boolean>;
14
+ toolboxOpen: any;
4
15
  orderedGroups: import("vue").ComputedRef<(import("../buttonManager.js", { with: { "resolution-mode": "import" } }).ButtonComponent | import("./toolboxManager.js", { with: { "resolution-mode": "import" } }).ToolboxComponent)[]>;
5
16
  zIndex: any;
6
17
  isDefaultToolbox: import("vue").ComputedRef<boolean>;
@@ -117,6 +117,11 @@ declare class ToolboxManager implements IToolboxManager {
117
117
  * @type {import("vue").UnwrapRef<string[]>}
118
118
  */
119
119
  componentIds: import("vue").UnwrapRef<string[]>;
120
+ /**
121
+ * reative boolean to show or hide the toolbox
122
+ * @type {import("vue").Ref<boolean>}
123
+ */
124
+ open: import("vue").Ref<boolean>;
120
125
  /**
121
126
  * @type {Map<string, ToolboxComponent>}
122
127
  * @private
@@ -1,7 +1,7 @@
1
1
  import { VcsEvent } from '@vcmap/core';
2
2
  import { check, maybe, ofEnum, oneOf, optional } from '@vcsuite/check';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
- import { reactive, shallowReactive } from 'vue';
4
+ import { reactive, ref, shallowReactive } from 'vue';
5
5
  import { vcsAppSymbol } from '../../pluginHelper.js';
6
6
  import ButtonManager from '../buttonManager.js';
7
7
  import { ActionPattern } from '../../components/lists/VcsActionList.vue';
@@ -207,6 +207,12 @@ class ToolboxManager {
207
207
  * @type {import("vue").UnwrapRef<string[]>}
208
208
  */
209
209
  this.componentIds = reactive([]);
210
+
211
+ /**
212
+ * reative boolean to show or hide the toolbox
213
+ * @type {import("vue").Ref<boolean>}
214
+ */
215
+ this.open = ref(true);
210
216
  /**
211
217
  * @type {Map<string, ToolboxComponent>}
212
218
  * @private
@@ -9,6 +9,7 @@
9
9
  :class="{
10
10
  rounded: !isDocked,
11
11
  marginToTop: isDocked || !isChild,
12
+ marginToTopTablet: isTabletWithOpenToolbar,
12
13
  'rounded-be': isDynamicLeft,
13
14
  'rounded-bs': isDynamicRight,
14
15
  }"
@@ -41,11 +42,15 @@
41
42
  .marginToTop {
42
43
  margin-top: 2px;
43
44
  }
45
+ .marginToTopTablet {
46
+ margin-top: calc(var(--v-vcs-font-size) * 3 + 6px);
47
+ }
44
48
  </style>
45
49
 
46
50
  <script>
47
51
  import { computed, inject, provide, ref } from 'vue';
48
52
  import { VDivider, VSheet } from 'vuetify/components';
53
+ import { useDisplay } from 'vuetify';
49
54
  import { WindowSlot } from './windowManager.js';
50
55
 
51
56
  /**
@@ -95,6 +100,10 @@
95
100
  const isDocked = computed(
96
101
  () => props.slotWindow.value !== WindowSlot.DETACHED,
97
102
  );
103
+ const display = useDisplay();
104
+ const isTabletWithOpenToolbar = computed(
105
+ () => app.toolboxManager.open.value && display.sm.value,
106
+ );
98
107
  const isDockedLeft = computed(() => {
99
108
  return (
100
109
  props.slotWindow.value === WindowSlot.STATIC ||
@@ -156,6 +165,7 @@
156
165
  isDynamic,
157
166
  isChild,
158
167
  isDocked,
168
+ isTabletWithOpenToolbar,
159
169
  isDynamicLeft: isDockedLeft,
160
170
  isDynamicRight: isDockedRight,
161
171
  isDraggable,