@vcmap/ui 6.1.0-rc.2 → 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 (105) 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-57fbd309.js → cesium-87d5e72d.js} +438 -432
  7. package/dist/assets/cesium.js +1 -1
  8. package/dist/assets/{core-fd079400.js → core-72f9f393.js} +4907 -4514
  9. package/dist/assets/core.js +1 -1
  10. package/dist/assets/{ol-50dfef96.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-5135917c.js → ui-73257b15.js} +13440 -12742
  14. package/dist/assets/ui.js +1 -1
  15. package/dist/assets/vue.js +1 -1
  16. package/dist/assets/{vuetify-f02b7bb9.css → vuetify-2437380c.css} +2 -2
  17. package/dist/assets/{vuetify-f02b7bb9.js → vuetify-2437380c.js} +8024 -7634
  18. package/dist/assets/vuetify.js +1 -1
  19. package/index.d.ts +38 -19
  20. package/index.js +35 -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 +24 -2
  32. package/src/application/VcsContainer.vue.d.ts +8 -0
  33. package/src/application/VcsObliqueFooter.vue +9 -3
  34. package/src/application/VcsSplashScreen.vue +37 -0
  35. package/src/application/VcsSplashScreen.vue.d.ts +6 -0
  36. package/src/application/positionDisplayInteraction.js +1 -1
  37. package/src/callback/activateClippingPolygonCallback.d.ts +29 -0
  38. package/src/callback/activateClippingPolygonCallback.js +54 -0
  39. package/src/callback/closeSplashScreenCallback.d.ts +8 -0
  40. package/src/callback/closeSplashScreenCallback.js +33 -0
  41. package/src/callback/deactivateClippingPolygonCallback.d.ts +29 -0
  42. package/src/callback/deactivateClippingPolygonCallback.js +54 -0
  43. package/src/callback/openSplashScreenCallback.d.ts +8 -0
  44. package/src/callback/openSplashScreenCallback.js +35 -0
  45. package/src/callback/toggleNavbarButtonCallback.d.ts +36 -0
  46. package/src/callback/toggleNavbarButtonCallback.js +62 -0
  47. package/src/components/form-inputs-controls/VcsSelect.vue +1 -1
  48. package/src/components/form-inputs-controls/VcsTextArea.vue +12 -7
  49. package/src/components/form-output/markdownHelper.d.ts +0 -25
  50. package/src/components/form-output/markdownHelper.js +1 -386
  51. package/src/components/lists/VcsGroupedList.vue +178 -0
  52. package/src/components/lists/VcsGroupedList.vue.d.ts +17 -0
  53. package/src/components/lists/VcsList.vue +142 -396
  54. package/src/components/lists/VcsList.vue.d.ts +38 -168
  55. package/src/components/lists/VcsTreeview.vue +11 -12
  56. package/src/components/lists/listHelper.d.ts +87 -0
  57. package/src/components/lists/listHelper.js +348 -0
  58. package/src/components/section/VcsFormSection.vue +7 -2
  59. package/src/components/section/VcsFormSection.vue.d.ts +9 -0
  60. package/src/components/vector-properties/VcsVectorPropertiesComponent.vue.d.ts +1 -1
  61. package/src/contentTree/LayerTree.vue +2 -1
  62. package/src/contentTree/LayerTree.vue.d.ts +2 -0
  63. package/src/contentTree/contentTreeCollection.d.ts +1 -0
  64. package/src/contentTree/contentTreeCollection.js +7 -3
  65. package/src/contentTree/contentTreeItem.js +4 -2
  66. package/src/contentTree/groupContentTreeItem.js +5 -3
  67. package/src/featureInfo/ClusterFeatureComponent.vue +58 -0
  68. package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +6 -0
  69. package/src/featureInfo/abstractFeatureInfoView.js +1 -2
  70. package/src/featureInfo/featureInfo.d.ts +87 -1
  71. package/src/featureInfo/featureInfo.js +342 -34
  72. package/src/featureInfo/featureInfoInteraction.js +18 -3
  73. package/src/featureInfo/iframeFeatureInfoView.js +1 -1
  74. package/src/featureInfo/markdownBalloonFeatureInfoView.js +2 -4
  75. package/src/featureInfo/markdownFeatureInfoView.js +1 -1
  76. package/src/i18n/de.d.ts +17 -4
  77. package/src/i18n/de.js +7 -0
  78. package/src/i18n/en.d.ts +17 -4
  79. package/src/i18n/en.js +7 -0
  80. package/src/legend/legendHelper.d.ts +1 -1
  81. package/src/legend/legendHelper.js +52 -9
  82. package/src/localStorage.d.ts +21 -0
  83. package/src/localStorage.js +51 -0
  84. package/src/manager/collectionManager/CollectionComponent.vue +1 -1
  85. package/src/manager/collectionManager/CollectionComponentContent.vue +2 -3
  86. package/src/manager/collectionManager/CollectionComponentList.vue +2 -3
  87. package/src/manager/collectionManager/CollectionComponentStandalone.vue +1 -1
  88. package/src/manager/navbarManager.js +9 -4
  89. package/src/manager/toolbox/ToolboxManagerComponent.vue +10 -8
  90. package/src/manager/toolbox/ToolboxManagerComponent.vue.d.ts +11 -0
  91. package/src/manager/window/windowHelper.d.ts +7 -3
  92. package/src/manager/window/windowHelper.js +30 -10
  93. package/src/navigation/overviewMap.d.ts +1 -0
  94. package/src/navigation/overviewMap.js +4 -3
  95. package/src/pluginHelper.d.ts +7 -0
  96. package/src/pluginHelper.js +18 -4
  97. package/src/search/ResultItem.vue.d.ts +1 -1
  98. package/src/search/search.js +1 -1
  99. package/src/state.d.ts +4 -2
  100. package/src/state.js +54 -31
  101. package/src/uiConfig.d.ts +27 -0
  102. package/src/uiConfig.js +16 -1
  103. package/src/vcsUiApp.js +7 -11
  104. package/dist/assets/ui-5135917c.css +0 -1
  105. /package/dist/assets/{vue-c3c55d88.js → vue-ff37ea23.js} +0 -0
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',
@@ -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
  }
@@ -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
 
@@ -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,19 +186,19 @@
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
204
  const { smAndUp } = useDisplay();
@@ -1,3 +1,14 @@
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
13
  smAndUp: import("vue").Ref<boolean>;
3
14
  toolboxOpen: any;
@@ -10,9 +10,11 @@ export function getTargetSize(target: HTMLElement): DOMRect | null;
10
10
  * @param {number} y - client pixel position
11
11
  * @param {HTMLElement} target - the map's target { @link @import("@vcmap/core").MapCollection }
12
12
  * @param {WindowAlignment} [alignment=WindowAlignment.TOP_LEFT]
13
+ * @param {number} [offsetX=0]
14
+ * @param {number} [offsetY=0]
13
15
  * @returns {import("./windowManager.js").WindowPositionOptions}
14
16
  */
15
- export function getWindowPositionOptions(x: number, y: number, target: HTMLElement, alignment?: number | undefined): import("./windowManager.js").WindowPositionOptions;
17
+ export function getWindowPositionOptions(x: number, y: number, target: HTMLElement, alignment?: number | undefined, offsetX?: number | undefined, offsetY?: number | undefined): import("./windowManager.js").WindowPositionOptions;
16
18
  /**
17
19
  * Get window position options based on a pixel in the map
18
20
  * @param {import("@vcmap-cesium/engine").Cartesian2} windowPosition - the window position, as retrieved from an InteractionEvent
@@ -28,10 +30,12 @@ export function getWindowPositionOptionsFromMapEvent(windowPosition: import("@vc
28
30
  * @param {number} y - client pixel position
29
31
  * @param {number} width - window width to fit
30
32
  * @param {number} height - window height to fit
31
- * @param {HTMLElement} target - the map's target { @link @import("@vcmap/core").MapCollection }
33
+ * @param {HTMLElement} target - the map's target { @link @import("@vcmap/core").MapCollection }
34
+ * @param {number} [offsetX=0]
35
+ * @param {number} [offsetY=0]
32
36
  * @returns {import("./windowManager.js").WindowPositionOptions}
33
37
  */
34
- export function getFittedWindowPositionOptions(x: number, y: number, width: number, height: number, target: HTMLElement): import("./windowManager.js").WindowPositionOptions;
38
+ export function getFittedWindowPositionOptions(x: number, y: number, width: number, height: number, target: HTMLElement, offsetX?: number | undefined, offsetY?: number | undefined): import("./windowManager.js").WindowPositionOptions;
35
39
  /**
36
40
  * Fits a window aligned top left, so it fits into currently active map. This will change the alignment to be bottom or right depending
37
41
  * on if the window would not fit into active map element.
@@ -49,6 +49,8 @@ export function getTargetSize(target) {
49
49
  * @param {number} y - client pixel position
50
50
  * @param {HTMLElement} target - the map's target { @link @import("@vcmap/core").MapCollection }
51
51
  * @param {WindowAlignment} [alignment=WindowAlignment.TOP_LEFT]
52
+ * @param {number} [offsetX=0]
53
+ * @param {number} [offsetY=0]
52
54
  * @returns {import("./windowManager.js").WindowPositionOptions}
53
55
  */
54
56
  export function getWindowPositionOptions(
@@ -56,6 +58,8 @@ export function getWindowPositionOptions(
56
58
  y,
57
59
  target,
58
60
  alignment = WindowAlignment.TOP_LEFT,
61
+ offsetX = 0,
62
+ offsetY = 0,
59
63
  ) {
60
64
  const targetSize = getTargetSize(target);
61
65
  if (!targetSize) {
@@ -64,13 +68,19 @@ export function getWindowPositionOptions(
64
68
 
65
69
  const { left, top, width, height } = targetSize;
66
70
  if (alignment === WindowAlignment.TOP_LEFT) {
67
- return { left: x - left, top: y - top };
71
+ return { left: x - left + offsetX, top: y - top - offsetY };
68
72
  } else if (alignment === WindowAlignment.TOP_RIGHT) {
69
- return { right: left + width - x, top: y - top };
73
+ return { right: left + width - x + offsetX, top: y - top - offsetY };
70
74
  } else if (alignment === WindowAlignment.BOTTOM_LEFT) {
71
- return { left: x - left, bottom: height + top - y };
75
+ return {
76
+ left: x - left + offsetX,
77
+ bottom: height + top - y - offsetY,
78
+ };
72
79
  }
73
- return { right: left + width - x, bottom: height + top - y };
80
+ return {
81
+ right: left + width - x + offsetX,
82
+ bottom: height + top - y - offsetY,
83
+ };
74
84
  }
75
85
 
76
86
  /**
@@ -106,18 +116,28 @@ export function getWindowPositionOptionsFromMapEvent(
106
116
  * @param {number} y - client pixel position
107
117
  * @param {number} width - window width to fit
108
118
  * @param {number} height - window height to fit
109
- * @param {HTMLElement} target - the map's target { @link @import("@vcmap/core").MapCollection }
119
+ * @param {HTMLElement} target - the map's target { @link @import("@vcmap/core").MapCollection }
120
+ * @param {number} [offsetX=0]
121
+ * @param {number} [offsetY=0]
110
122
  * @returns {import("./windowManager.js").WindowPositionOptions}
111
123
  */
112
- export function getFittedWindowPositionOptions(x, y, width, height, target) {
124
+ export function getFittedWindowPositionOptions(
125
+ x,
126
+ y,
127
+ width,
128
+ height,
129
+ target,
130
+ offsetX = 0,
131
+ offsetY = 0,
132
+ ) {
113
133
  const targetSize = getTargetSize(target);
114
134
  if (!targetSize) {
115
135
  return { left: x, top: y };
116
136
  }
117
137
 
118
- const { width: parentWidth, height: parentHeight } = targetSize;
119
- const bottom = y + height > parentHeight;
120
- const right = x + width > parentWidth;
138
+ const { left, top, width: parentWidth, height: parentHeight } = targetSize;
139
+ const bottom = y - top + height > parentHeight && y - top > parentHeight / 2;
140
+ const right = x - left + width > parentWidth && x - left > parentWidth / 2;
121
141
  let alignment = WindowAlignment.TOP_LEFT;
122
142
  if (bottom) {
123
143
  if (right) {
@@ -128,7 +148,7 @@ export function getFittedWindowPositionOptions(x, y, width, height, target) {
128
148
  } else if (right) {
129
149
  alignment = WindowAlignment.TOP_RIGHT;
130
150
  }
131
- return getWindowPositionOptions(x, y, target, alignment);
151
+ return getWindowPositionOptions(x, y, target, alignment, offsetX, offsetY);
132
152
  }
133
153
 
134
154
  /**
@@ -2,6 +2,7 @@
2
2
  * @returns {import("../manager/window/windowManager.js").WindowComponentOptions}
3
3
  */
4
4
  export function getWindowComponentOptions(): import("../manager/window/windowManager.js").WindowComponentOptions;
5
+ export const overviewMapWindowId: "overview-map-container";
5
6
  export const overviewMapLayerSymbol: unique symbol;
6
7
  export default OverviewMap;
7
8
  /**
@@ -30,6 +30,7 @@ import {
30
30
  import { vcsAppSymbol } from '../pluginHelper.js';
31
31
  import VcsMap from '../application/VcsMap.vue';
32
32
 
33
+ export const overviewMapWindowId = 'overview-map-container';
33
34
  export const overviewMapLayerSymbol = Symbol('overviewMapLayerSymbol');
34
35
 
35
36
  /**
@@ -40,7 +41,7 @@ export function getWindowComponentOptions() {
40
41
  component: VcsMap,
41
42
  props: { mapId: 'overview-map-container' },
42
43
  slot: WindowSlot.DETACHED,
43
- id: 'overview-map-container',
44
+ id: overviewMapWindowId,
44
45
  state: {
45
46
  hideHeader: true,
46
47
  classes: ['overview-map'],
@@ -361,7 +362,7 @@ class OverviewMap {
361
362
  * @returns {Promise<void>}
362
363
  */
363
364
  async activate() {
364
- if (!this._app.windowManager.has('overview-map-container')) {
365
+ if (!this._app.windowManager.has(overviewMapWindowId)) {
365
366
  this._app.windowManager.add(getWindowComponentOptions(), vcsAppSymbol);
366
367
  }
367
368
  await this._activate();
@@ -371,7 +372,7 @@ class OverviewMap {
371
372
  * closes window and clears all listeners
372
373
  */
373
374
  deactivate() {
374
- this._app.windowManager.remove('overview-map-container');
375
+ this._app.windowManager.remove(overviewMapWindowId);
375
376
  this._clearListeners();
376
377
  if (this._mapActivatedListener) {
377
378
  this._mapActivatedListener();
@@ -15,6 +15,13 @@ export function getPluginAssetUrl(app: import("@src/vcsUiApp.js").default, plugi
15
15
  * @returns {boolean}
16
16
  */
17
17
  export function isValidPackageName(name: string): boolean;
18
+ /**
19
+ * joins pathname and moduleUrl.
20
+ * @param {string} pathname will remove filenames with extension or add a trailing slash if missing
21
+ * @param {string} module relative url to the module
22
+ * @returns {string}
23
+ */
24
+ export function getModuleUrl(pathname: string, module: string): string;
18
25
  /**
19
26
  * @param {string} name
20
27
  * @param {T} config
@@ -82,6 +82,23 @@ export function isValidPackageName(name) {
82
82
  );
83
83
  }
84
84
 
85
+ /**
86
+ * joins pathname and moduleUrl.
87
+ * @param {string} pathname will remove filenames with extension or add a trailing slash if missing
88
+ * @param {string} module relative url to the module
89
+ * @returns {string}
90
+ */
91
+ export function getModuleUrl(pathname, module) {
92
+ const pathNameParts = pathname.split('/');
93
+ if (pathNameParts.at(-1).includes('.')) {
94
+ pathNameParts.pop();
95
+ } else if (pathNameParts.at(-1) === '') {
96
+ pathNameParts.pop();
97
+ }
98
+ const pathName = pathNameParts.join('/');
99
+ return `${pathName}/${module}`;
100
+ }
101
+
85
102
  /**
86
103
  * @param {string} name
87
104
  * @param {T} config
@@ -93,10 +110,7 @@ export async function loadPlugin(name, config) {
93
110
  let module = config.entry;
94
111
 
95
112
  if (!/^(https?:\/\/|\/)/.test(module)) {
96
- module = `${window.location.origin}${window.location.pathname.replace(
97
- /\/?$/,
98
- '/',
99
- )}${module}`;
113
+ module = `${window.location.origin}${getModuleUrl(window.location.pathname, module)}`;
100
114
  } else if (module === '_dev') {
101
115
  module = `/${name}.js`;
102
116
  } else if (module === 'http://localhost/_test') {
@@ -9,7 +9,7 @@ declare const _default: import("vue").DefineComponent<{
9
9
  };
10
10
  }, {
11
11
  hasActions: import("vue").ComputedRef<boolean>;
12
- marked: import("vue").ComputedRef<any>;
12
+ marked: import("vue").ComputedRef<string>;
13
13
  }, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
14
14
  query: {
15
15
  type: StringConstructor;
@@ -318,7 +318,7 @@ class Search extends IndexedCollection {
318
318
  this._app.featureInfo.selectedFeature?.[vcsLayerName] ===
319
319
  this._resultLayer.name
320
320
  ) {
321
- this._app.featureInfo.clear();
321
+ this._app.featureInfo.clearSelection();
322
322
  }
323
323
  }
324
324
 
package/src/state.d.ts CHANGED
@@ -4,14 +4,16 @@
4
4
  export function createEmptyState(): AppState;
5
5
  /**
6
6
  * @param {UrlViewpointState} state
7
+ * @param {string} moduleId
7
8
  * @returns {import("@vcmap/core").ViewpointOptions|null}
8
9
  */
9
- export function parseUrlProjectedViewpointState(state: UrlViewpointState): import("@vcmap/core").ViewpointOptions | null;
10
+ export function parseUrlProjectedViewpointState(state: UrlViewpointState, moduleId: string): import("@vcmap/core").ViewpointOptions | null;
10
11
  /**
11
12
  * @param {UrlExtentState} state
13
+ * @param {string} moduleId
12
14
  * @returns {import("@vcmap/core").ViewpointOptions|null}
13
15
  */
14
- export function parseUrlExtentState(state: UrlExtentState): import("@vcmap/core").ViewpointOptions | null;
16
+ export function parseUrlExtentState(state: UrlExtentState, moduleId: string): import("@vcmap/core").ViewpointOptions | null;
15
17
  /**
16
18
  * @param {(URL)=} url
17
19
  * @returns {AppState}