@vcmap/ui 6.2.1 → 6.2.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 (62) hide show
  1. package/build/postInstall.js +1 -1
  2. package/config/dev.config.json +1 -1
  3. package/dist/assets/{cesium-607748ca.js → cesium-dcdef786.js} +1513 -1313
  4. package/dist/assets/cesium.js +1 -1
  5. package/dist/assets/{core-ea8a27bd.js → core-f4ee6bea.js} +1554 -1551
  6. package/dist/assets/core-workers/panoramaImageWorker.js +1 -1
  7. package/dist/assets/core.js +1 -1
  8. package/dist/assets/{ol-8fe80c53.js → ol-f7a5160f.js} +1 -1
  9. package/dist/assets/ol.js +1 -1
  10. package/dist/assets/ui-d3a7bd39.css +1 -0
  11. package/dist/assets/{ui-ffa735dc.js → ui-d3a7bd39.js} +7725 -7494
  12. package/dist/assets/ui.js +1 -1
  13. package/dist/assets/vue.js +1 -1
  14. package/dist/assets/{vuetify-def19d80.js → vuetify-8e1623b2.js} +1 -1
  15. package/dist/assets/vuetify.js +1 -1
  16. package/index.d.ts +3 -1
  17. package/index.js +2 -0
  18. package/package.json +4 -3
  19. package/plugins/@vcmap-show-case/category-tester/src/CollectionComponentOptions.vue +41 -2
  20. package/plugins/@vcmap-show-case/category-tester/src/index.js +2 -0
  21. package/src/application/VcsSettings.vue +4 -0
  22. package/src/application/VcsSplashScreen.vue +9 -1
  23. package/src/components/flight/VcsFlightAnchorsComponent.vue +2 -2
  24. package/src/components/lists/VcsList.vue +10 -18
  25. package/src/components/lists/VcsTreeNode.vue +10 -4
  26. package/src/components/lists/VcsTreeNode.vue.d.ts +8 -0
  27. package/src/components/lists/VcsTreeview.vue +2 -6
  28. package/src/components/lists/VcsTreeview.vue.d.ts +0 -1
  29. package/src/components/lists/dragHelper.d.ts +9 -2
  30. package/src/components/lists/dragHelper.js +47 -21
  31. package/src/contentTree/LayerSwap.vue +24 -4
  32. package/src/contentTree/LayerSwap.vue.d.ts +18 -4
  33. package/src/contentTree/wmsGroupContentTreeItem.d.ts +22 -3
  34. package/src/contentTree/wmsGroupContentTreeItem.js +126 -64
  35. package/src/featureInfo/balloonFeatureInfoView.d.ts +15 -2
  36. package/src/featureInfo/balloonFeatureInfoView.js +8 -103
  37. package/src/featureInfo/balloonHelper.d.ts +13 -0
  38. package/src/featureInfo/balloonHelper.js +77 -0
  39. package/src/featureInfo/featureInfo.d.ts +2 -1
  40. package/src/featureInfo/featureInfo.js +11 -3
  41. package/src/featureInfo/featureInfoInteraction.js +4 -1
  42. package/src/featureInfo/iframeWmsFeatureInfoView.js +12 -2
  43. package/src/i18n/de.d.ts +3 -0
  44. package/src/i18n/de.js +3 -0
  45. package/src/i18n/en.d.ts +3 -0
  46. package/src/i18n/en.js +3 -0
  47. package/src/legend/legendHelper.js +5 -0
  48. package/src/manager/collectionManager/CollectionComponentContent.vue +69 -5
  49. package/src/manager/collectionManager/CollectionComponentContent.vue.d.ts +3 -0
  50. package/src/manager/collectionManager/CollectionComponentList.vue +2 -24
  51. package/src/manager/collectionManager/CollectionComponentList.vue.d.ts +0 -8
  52. package/src/manager/collectionManager/collectionComponentClass.d.ts +44 -1
  53. package/src/manager/collectionManager/collectionComponentClass.js +152 -2
  54. package/src/manager/panel/PanelComponent.vue +9 -1
  55. package/src/state.d.ts +14 -0
  56. package/src/state.js +60 -6
  57. package/src/vcsUiApp.d.ts +9 -36
  58. package/src/vcsUiApp.js +45 -11
  59. package/dist/assets/ui-ffa735dc.css +0 -1
  60. /package/dist/assets/core-workers/{panoramaImageWorker.js-a3ad230c.js → panoramaImageWorker.js-a6bb36f6.js} +0 -0
  61. /package/dist/assets/{vue-09a72820.js → vue-cbd2bd60.js} +0 -0
  62. /package/dist/assets/{vuetify-def19d80.css → vuetify-8e1623b2.css} +0 -0
package/dist/assets/ui.js CHANGED
@@ -1 +1 @@
1
- export * from "./ui-ffa735dc.js";
1
+ export * from "./ui-d3a7bd39.js";
@@ -1 +1 @@
1
- export * from "./vue-09a72820.js";
1
+ export * from "./vue-cbd2bd60.js";
@@ -10,7 +10,7 @@ function loadCss(href) {
10
10
  elem.onerror = reject;
11
11
  document.head.appendChild(elem);
12
12
  });
13
- } await loadCss('./assets/vuetify-def19d80.css');import { watch as Q, onScopeDispose as Ze, effectScope as Zl, shallowRef as K, Fragment as ie, reactive as it, computed as b, watchEffect as Fe, toRefs as Yt, capitalize as Nn, isVNode as Rc, Comment as Nc, unref as ot, warn as ja, getCurrentInstance as Hc, ref as j, provide as De, inject as ye, defineComponent as zc, camelize as Ir, h as Gt, toRaw as Be, createVNode as r, mergeProps as O, onBeforeUnmount as Qe, readonly as Ql, onDeactivated as _r, onActivated as Wc, onMounted as Ye, nextTick as we, TransitionGroup as Jl, Transition as jt, isRef as Tn, toRef as $, onBeforeMount as ra, withDirectives as $e, resolveDirective as gt, vShow as Ct, onUpdated as jc, Text as Uc, resolveDynamicComponent as Yc, markRaw as Gc, Teleport as Kc, cloneVNode as qc, createTextVNode as Tt, onUnmounted as Tr, onBeforeUpdate as Xc, withModifiers as Tl, toDisplayString as Zc, vModelText as Qc, resolveComponent as Jc, render as Ar } from "./vue-09a72820.js";
13
+ } await loadCss('./assets/vuetify-8e1623b2.css');import { watch as Q, onScopeDispose as Ze, effectScope as Zl, shallowRef as K, Fragment as ie, reactive as it, computed as b, watchEffect as Fe, toRefs as Yt, capitalize as Nn, isVNode as Rc, Comment as Nc, unref as ot, warn as ja, getCurrentInstance as Hc, ref as j, provide as De, inject as ye, defineComponent as zc, camelize as Ir, h as Gt, toRaw as Be, createVNode as r, mergeProps as O, onBeforeUnmount as Qe, readonly as Ql, onDeactivated as _r, onActivated as Wc, onMounted as Ye, nextTick as we, TransitionGroup as Jl, Transition as jt, isRef as Tn, toRef as $, onBeforeMount as ra, withDirectives as $e, resolveDirective as gt, vShow as Ct, onUpdated as jc, Text as Uc, resolveDynamicComponent as Yc, markRaw as Gc, Teleport as Kc, cloneVNode as qc, createTextVNode as Tt, onUnmounted as Tr, onBeforeUpdate as Xc, withModifiers as Tl, toDisplayString as Zc, vModelText as Qc, resolveComponent as Jc, render as Ar } from "./vue-cbd2bd60.js";
14
14
  function rt(e, n) {
15
15
  let t;
16
16
  function a() {
@@ -1 +1 @@
1
- export * from "./vuetify-def19d80.js";
1
+ export * from "./vuetify-8e1623b2.js";
package/index.d.ts CHANGED
@@ -209,6 +209,8 @@ export * from "./src/components/modelHelper.js";
209
209
  export type * from "./src/components/modelHelper.d.ts";
210
210
  export * from "./src/components/composables.js";
211
211
  export type * from "./src/components/composables.d.ts";
212
+ export { moveDraggableItems } from "./src/components/lists/dragHelper.js";
213
+ export type * from "./src/components/lists/dragHelper.d.ts";
212
214
  export { default as VcsTreeview } from "./src/components/lists/VcsTreeview.vue";
213
215
  export type * from "./src/components/lists/VcsTreeview.vue.d.ts";
214
216
  export { default as VcsTreeNode } from "./src/components/lists/VcsTreeNode.vue";
@@ -325,7 +327,7 @@ export { applyKeyMapping, applyValueMapping, default as AbstractFeatureInfoView
325
327
  export type * from "./src/featureInfo/abstractFeatureInfoView.d.ts";
326
328
  export { extractNestedKey, default as BalloonFeatureInfoView } from "./src/featureInfo/balloonFeatureInfoView.js";
327
329
  export type * from "./src/featureInfo/balloonFeatureInfoView.d.ts";
328
- export { getBalloonPosition, setBalloonPosition, setupBalloonPositionListener } from "./src/featureInfo/balloonHelper.js";
330
+ export { getBalloonPosition, setBalloonPosition, setupBalloonPositionListener, getBalloonPositionFromFeature } from "./src/featureInfo/balloonHelper.js";
329
331
  export type * from "./src/featureInfo/balloonHelper.d.ts";
330
332
  export { getHighlightStyleFromStyle, getHighlightStyle, getClusterHighlightStyle, featureInfoViewSymbol } from "./src/featureInfo/featureInfo.js";
331
333
  export type * from "./src/featureInfo/featureInfo.d.ts";
package/index.js CHANGED
@@ -191,6 +191,7 @@ export {
191
191
  getBalloonPosition,
192
192
  setBalloonPosition,
193
193
  setupBalloonPositionListener,
194
+ getBalloonPositionFromFeature,
194
195
  } from './src/featureInfo/balloonHelper.js';
195
196
  export { default as BalloonComponent } from './src/featureInfo/BalloonComponent.vue';
196
197
  export { default as AddressBalloonComponent } from './src/featureInfo/AddressBalloonComponent.vue';
@@ -312,6 +313,7 @@ export { default as VcsList } from './src/components/lists/VcsList.vue';
312
313
  export { default as VcsListItemComponent } from './src/components/lists/VcsListItemComponent.vue';
313
314
  export { default as VcsGroupedList } from './src/components/lists/VcsGroupedList.vue';
314
315
  export * from './src/components/lists/listHelper.js';
316
+ export { moveDraggableItems } from './src/components/lists/dragHelper.js';
315
317
  export { default as VcsTreeview } from './src/components/lists/VcsTreeview.vue';
316
318
  export { default as VcsTreeNode } from './src/components/lists/VcsTreeNode.vue';
317
319
  export { default as VcsTreeviewTitle } from './src/components/lists/VcsTreeviewTitle.vue';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/ui",
3
- "version": "6.2.1",
3
+ "version": "6.2.3",
4
4
  "author": "Virtual City Systems",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -58,13 +58,14 @@
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@vcmap-cesium/engine": "^11.0.3",
61
- "@vcmap/core": "^6.2.2",
61
+ "@vcmap/core": "^6.2.3",
62
62
  "ol": "^10.4.0",
63
63
  "vue": "~3.4.38",
64
64
  "vuetify": "~3.7.14"
65
65
  },
66
66
  "overrides": {
67
- "esbuild": "^0.25.0"
67
+ "esbuild": "^0.25.0",
68
+ "@zip.js/zip.js": "2.7.68"
68
69
  },
69
70
  "devDependencies": {
70
71
  "@histoire/plugin-vue": "^0.17.17",
@@ -24,13 +24,22 @@
24
24
  />
25
25
  </v-col>
26
26
  </v-row>
27
+ <v-row no-gutters>
28
+ <v-col>
29
+ <VcsLabel>{{ $st(`pagination`) }}</VcsLabel>
30
+ </v-col>
31
+ <v-col>
32
+ <VcsCheckbox v-model="pagination" />
33
+ </v-col>
34
+ </v-row>
27
35
  </v-container>
28
36
  </template>
29
37
 
30
38
  <script>
31
- import { inject, isRef, reactive } from 'vue';
39
+ import { inject, isRef, reactive, watch, ref } from 'vue';
32
40
  import { VContainer, VRow, VCol } from 'vuetify/components';
33
41
  import { VcsCheckbox, VcsLabel, VcsTextField } from '@vcmap/ui';
42
+ import { Collection } from '@vcmap/core';
34
43
 
35
44
  /**
36
45
  * Shows CollectionComponentOptions of a provided collectionComponent
@@ -45,7 +54,9 @@
45
54
  VRow,
46
55
  VCol,
47
56
  },
57
+ props: {},
48
58
  setup() {
59
+ /** @type {import("@vcmap/ui").CollectionComponentClass} */
49
60
  const collectionComponent = inject('collectionComponent');
50
61
  const localOptions = reactive({
51
62
  draggable: collectionComponent.draggable,
@@ -54,7 +65,34 @@
54
65
  renamable: collectionComponent.renamable,
55
66
  removable: collectionComponent.removable,
56
67
  });
57
-
68
+ // clone is for demonstration purposes only: caches the original items while pagination is active.
69
+ const collectionClone = new Collection();
70
+ const pagination = ref(!!collectionComponent.pagination.value);
71
+ watch(pagination, (value) => {
72
+ if (value) {
73
+ collectionClone.clear();
74
+ [...collectionComponent.collection].forEach((item) => {
75
+ collectionClone.add(item);
76
+ });
77
+ collectionComponent.setPagination({
78
+ // just for demonstration purposes -> get Items should fetch items from server.
79
+ getItems(startIndex, count) {
80
+ return {
81
+ items: [...collectionClone].slice(
82
+ startIndex,
83
+ count + startIndex,
84
+ ),
85
+ total: collectionClone.size,
86
+ };
87
+ },
88
+ });
89
+ } else {
90
+ collectionComponent.setPagination(undefined);
91
+ [...collectionClone].forEach((item) => {
92
+ collectionComponent.collection.add(item);
93
+ });
94
+ }
95
+ });
58
96
  return {
59
97
  title: collectionComponent.title,
60
98
  keys: Object.keys(localOptions),
@@ -67,6 +105,7 @@
67
105
  collectionComponent[key] = value;
68
106
  }
69
107
  },
108
+ pagination,
70
109
  };
71
110
  },
72
111
  };
@@ -54,6 +54,7 @@ export default async function categoryTest() {
54
54
  singleSelect: 'Einfachauswahl',
55
55
  renamable: 'umbenennbar',
56
56
  removable: 'löschbar',
57
+ pagination: 'Pagination',
57
58
  fooEditor: {
58
59
  name: 'Name',
59
60
  title: 'Titel',
@@ -70,6 +71,7 @@ export default async function categoryTest() {
70
71
  singleSelect: 'single select',
71
72
  renamable: 'renamable',
72
73
  removable: 'removable',
74
+ pagination: 'Pagination',
73
75
  fooEditor: {
74
76
  name: 'Name',
75
77
  title: 'Title',
@@ -99,6 +99,10 @@
99
99
  };
100
100
  setupI18n();
101
101
  const setLocale = () => {
102
+ if (!languages.value.includes(app.locale)) {
103
+ localLanguage.value = 'en';
104
+ return;
105
+ }
102
106
  localLanguage.value = app.locale;
103
107
  };
104
108
  setLocale();
@@ -12,6 +12,9 @@
12
12
  <v-card>
13
13
  <v-card-text class="pb-0 overflow-y-auto">
14
14
  <VcsMarkdown :content="$st(options.content)" />
15
+ </v-card-text>
16
+
17
+ <div class="vcs-splash-screen-checkboxes px-8">
15
18
  <VcsCheckbox v-if="options.acceptInput" v-model="checkBox">
16
19
  <template #label>
17
20
  <VcsMarkdown
@@ -32,7 +35,7 @@
32
35
  </div>
33
36
  </template>
34
37
  </VcsCheckbox>
35
- </v-card-text>
38
+ </div>
36
39
 
37
40
  <v-card-actions class="vcs-splash-screen-actions">
38
41
  <div class="d-flex gc-2 w-100 justify-end">
@@ -197,4 +200,9 @@
197
200
  position: sticky !important;
198
201
  bottom: 0;
199
202
  }
203
+ .vcs-splash-screen-checkboxes {
204
+ background-color: rgb(var(--v-theme-surface));
205
+ position: sticky !important;
206
+ bottom: 0;
207
+ }
200
208
  </style>
@@ -73,7 +73,7 @@
73
73
  import VcsList from '../lists/VcsList.vue';
74
74
  import VcsTextField from '../form-inputs-controls/VcsTextField.vue';
75
75
  import VcsButton from '../buttons/VcsButton.vue';
76
- import { moveItem } from '../../manager/collectionManager/CollectionComponentList.vue';
76
+ import { moveItem } from '../lists/dragHelper.js';
77
77
  import CollectionComponentClass from '../../manager/collectionManager/collectionComponentClass.js';
78
78
  import { WindowSlot } from '../../manager/window/windowManager.js';
79
79
  import VcsViewpointEditor from '../viewpoint/VcsViewpointEditor.vue';
@@ -330,7 +330,7 @@
330
330
  draggable: collectionComponent.draggable,
331
331
  actions: collectionComponent.getActions(),
332
332
  move(event) {
333
- moveItem(collectionComponent, event);
333
+ moveItem(collectionComponent.collection, event);
334
334
  },
335
335
  durationRule,
336
336
  showDuration(index) {
@@ -46,7 +46,6 @@
46
46
  "
47
47
  @dragend="dragEnd($event)"
48
48
  @drop="drop($event, item)"
49
- @dragleave="dragLeave($event)"
50
49
  :class="{
51
50
  'v-list-item__selected': selected.includes(item),
52
51
  'v-list-item__lighten_even': lightenEven,
@@ -246,23 +245,16 @@
246
245
  return items;
247
246
  });
248
247
 
249
- const {
250
- dragging,
251
- isDraggable,
252
- dragStart,
253
- dragOver,
254
- dragLeave,
255
- dragEnd,
256
- drop,
257
- } = setupDraggableListOrTree(props, query, (e, value) =>
258
- emit(e, {
259
- ...value,
260
- // @deprecate: targetIndex will be removed on next mayor release
261
- targetIndex: props.items.findIndex(
262
- (i) => i.name === value.targetItem.name,
263
- ),
264
- }),
265
- );
248
+ const { dragging, isDraggable, dragStart, dragOver, dragEnd, drop } =
249
+ setupDraggableListOrTree(props, query, (e, value) =>
250
+ emit(e, {
251
+ ...value,
252
+ // @deprecate: targetIndex will be removed on next mayor release
253
+ targetIndex: props.items.findIndex(
254
+ (i) => i.name === value.targetItem.name,
255
+ ),
256
+ }),
257
+ );
266
258
 
267
259
  const { select, selected, selectionActions } = setupSelectableList(
268
260
  props,
@@ -14,12 +14,13 @@
14
14
  ref="treenodeRef"
15
15
  no-gutters
16
16
  class="treenode flex-nowrap text-truncate"
17
- :class="`level-${level} ${children.length ? 'group' : 'item'}`"
17
+ :class="`level-${level} ${isGroup ? 'group' : 'item'}`"
18
18
  >
19
19
  <VBtn
20
- v-if="children.length"
20
+ v-if="isGroup"
21
21
  class="chevron-btn"
22
22
  variant="text"
23
+ :disabled="item.children.length === 0"
23
24
  :icon="isOpen ? 'mdi-chevron-down' : 'mdi-chevron-right'"
24
25
  @click="bubbleItemToggled(item.name)"
25
26
  />
@@ -41,7 +42,7 @@
41
42
  <slot name="title" v-bind="{ item }">
42
43
  <VcsTreeviewTitle
43
44
  :item="item"
44
- :cursor-pointer="item.clickable || (openOnClick && !!children.length)"
45
+ :cursor-pointer="item.clickable || (openOnClick && isGroup)"
45
46
  @click="(event) => $emit('click', item, event)"
46
47
  />
47
48
  </slot>
@@ -53,7 +54,7 @@
53
54
  :disabled="item.disabled"
54
55
  right
55
56
  tooltip-position="right"
56
- block-overflow
57
+ :block-overflow="item.blockOverflow ?? true"
57
58
  class="col-4 pa-0 ml-auto pr-4"
58
59
  />
59
60
  </slot>
@@ -133,6 +134,8 @@
133
134
  * @property {Array<VcsTreeNodeItem>} [children] - An optional array of children. Can be binded to another key, using the `item-children` attributes of the VcsTreeview component.
134
135
  * @property {string|HTMLCanvasElement|HTMLImageElement|undefined} [icon] - An optional icon to display with this item. Can be a URL or HTMLElement.
135
136
  * @property {function(string):void} [clicked] - A callback called when the item is clicked.
137
+ * @property {boolean} [blockOverflow=true] - Forwards the blockOverflow setting to the ActionButtonList, if true will reserve some space for an overflow.
138
+ * @property {boolean} [forceNodeDisplay] - Forces the item to display as a node (with chevron) even when it has no children.
136
139
  */
137
140
 
138
141
  /**
@@ -253,6 +256,9 @@
253
256
  forwardSlots,
254
257
  treenodeRef,
255
258
  isOpen,
259
+ isGroup: computed(
260
+ () => children.value.length > 0 || props.item.forceNodeDisplay,
261
+ ),
256
262
  matchFilter,
257
263
  iconSize,
258
264
  children,
@@ -28,4 +28,12 @@ export type VcsTreeNodeItem = {
28
28
  * - A callback called when the item is clicked.
29
29
  */
30
30
  clicked?: ((arg0: string) => void) | undefined;
31
+ /**
32
+ * - Forwards the blockOverflow setting to the ActionButtonList, if true will reserve some space for an overflow.
33
+ */
34
+ blockOverflow?: boolean | undefined;
35
+ /**
36
+ * - Forces the item to display as a node (with chevron) even when it has no children.
37
+ */
38
+ forceNodeDisplay?: boolean | undefined;
31
39
  };
@@ -36,7 +36,6 @@
36
36
  @dragover="dragOver"
37
37
  @dragend="dragEnd"
38
38
  @drop="drop"
39
- @dragleave="dragLeave"
40
39
  @item-toggled="itemToggled"
41
40
  @click="itemClicked"
42
41
  >
@@ -150,9 +149,7 @@
150
149
  localOpenedItems.value.push(...newItems);
151
150
  }
152
151
  },
153
- {
154
- immediate: true,
155
- },
152
+ { immediate: true },
156
153
  );
157
154
 
158
155
  function itemToggled(itemName) {
@@ -166,14 +163,13 @@
166
163
 
167
164
  const { xs } = useDisplay();
168
165
 
169
- const { isDraggable, dragStart, dragOver, dragLeave, dragEnd, drop } =
166
+ const { isDraggable, dragStart, dragOver, dragEnd, drop } =
170
167
  setupDraggableListOrTree(props, localSearchValue, emit);
171
168
 
172
169
  return {
173
170
  isDraggable,
174
171
  dragStart,
175
172
  dragOver,
176
- dragLeave,
177
173
  dragEnd,
178
174
  drop,
179
175
  localSearchValue,
@@ -51,7 +51,6 @@ declare const _default: import("vue").DefineComponent<{
51
51
  isDraggable: import("vue").ComputedRef<boolean>;
52
52
  dragStart: (e: MouseEvent, item: import("./dragHelper.js", { with: { "resolution-mode": "import" } }).VcsDraggableItem) => void;
53
53
  dragOver: (e: MouseEvent, item: import("./dragHelper.js", { with: { "resolution-mode": "import" } }).VcsDraggableItem, dropTarget: HTMLElement, dropTargetZones?: import("./dragHelper.js", { with: { "resolution-mode": "import" } }).DropZones | undefined, isOpen?: boolean | undefined) => void;
54
- dragLeave: (e: MouseEvent) => void;
55
54
  dragEnd: (e: MouseEvent) => void;
56
55
  drop: (e: MouseEvent, item: import("./dragHelper.js", { with: { "resolution-mode": "import" } }).VcsDraggableItem) => void;
57
56
  localSearchValue: import("vue").Ref<any>;
@@ -30,7 +30,6 @@
30
30
  * dropTargetZones?: DropZones,
31
31
  * isOpen?: boolean,
32
32
  * ) => void;
33
- * dragLeave: (e: MouseEvent) => void;
34
33
  * dragEnd: (e: MouseEvent) => void;
35
34
  * drop: (
36
35
  * e: MouseEvent,
@@ -78,6 +77,15 @@ export function setupDraggableListOrTree(props: Object & {
78
77
  * @param {ItemMovedEvent} event
79
78
  */
80
79
  export function moveDraggableItems(items: Array<VcsDraggableItem>, { item, targetItem, position }: ItemMovedEvent): void;
80
+ /**
81
+ * Moves an item to a new position.
82
+ * New position is derived from a target item in the collection.
83
+ * This ensures correct movement, if rendered list is only a subset of the collection.
84
+ * @template T
85
+ * @param {import("@vcmap/core").IndexedCollection<T>} collection
86
+ * @param {import("../../components/lists/dragHelper.js").ItemMovedEvent} event
87
+ */
88
+ export function moveItem<T>(collection: import("@vcmap/core").IndexedCollection<T>, event: import("../../components/lists/dragHelper.js").ItemMovedEvent): void;
81
89
  export type InsertMode = number;
82
90
  export namespace InsertMode {
83
91
  let BEFORE: number;
@@ -96,7 +104,6 @@ export type DraggableListOrTreeSetup = {
96
104
  isDraggable: import("vue").ComputedRef<boolean>;
97
105
  dragStart: (e: MouseEvent, item: VcsDraggableItem) => void;
98
106
  dragOver: (e: MouseEvent, item: VcsDraggableItem, dropTarget: HTMLElement, dropTargetZones?: DropZones, isOpen?: boolean) => void;
99
- dragLeave: (e: MouseEvent) => void;
100
107
  dragEnd: (e: MouseEvent) => void;
101
108
  drop: (e: MouseEvent, item: VcsDraggableItem) => void;
102
109
  };
@@ -43,7 +43,6 @@ export const InsertMode = {
43
43
  * dropTargetZones?: DropZones,
44
44
  * isOpen?: boolean,
45
45
  * ) => void;
46
- * dragLeave: (e: MouseEvent) => void;
47
46
  * dragEnd: (e: MouseEvent) => void;
48
47
  * drop: (
49
48
  * e: MouseEvent,
@@ -100,6 +99,11 @@ export function setupDraggableListOrTree(props, query, emit) {
100
99
  return !query.value && props.draggable;
101
100
  });
102
101
 
102
+ /**
103
+ * @type {HTMLElement | undefined}
104
+ */
105
+ let lastDropTarget;
106
+
103
107
  /**
104
108
  *
105
109
  * @param {HTMLElement} target
@@ -148,7 +152,7 @@ export function setupDraggableListOrTree(props, query, emit) {
148
152
  ) {
149
153
  dropPosition = InsertMode.AFTER;
150
154
  currentTarget.classList.add('drop-target-after');
151
- } else if (dropTargetZones === true || dropTargetZones.into === true) {
155
+ } else if (isIntoAllowed) {
152
156
  dropPosition = InsertMode.INTO;
153
157
  currentTarget.classList.add('drop-target-into');
154
158
  e.dataTransfer.dropEffect = 'copy';
@@ -158,7 +162,7 @@ export function setupDraggableListOrTree(props, query, emit) {
158
162
  }
159
163
 
160
164
  /**
161
- * @param {MouseEvent} e
165
+ * @param {DragEvent} e
162
166
  * @param {VcsDraggableItem} item
163
167
  */
164
168
  function drop(e, item) {
@@ -178,7 +182,7 @@ export function setupDraggableListOrTree(props, query, emit) {
178
182
  }
179
183
 
180
184
  /**
181
- * @param {MouseEvent} e
185
+ * @param {DragEvent} e
182
186
  * @param {VcsDraggableItem} item
183
187
  */
184
188
  function dragStart(e, item) {
@@ -191,7 +195,7 @@ export function setupDraggableListOrTree(props, query, emit) {
191
195
  }
192
196
 
193
197
  /**
194
- * @param {MouseEvent} e
198
+ * @param {DragEvent} e
195
199
  * @param {VcsDraggableItem} item
196
200
  * @param {HTMLElement} dropTarget
197
201
  * @param {DropZones} [dropTargetZones=true]
@@ -207,14 +211,22 @@ export function setupDraggableListOrTree(props, query, emit) {
207
211
  e.stopPropagation();
208
212
  e.preventDefault();
209
213
  if (
210
- !isDraggable.value ||
211
- !dragging.value ||
212
- draggedItem?.name === item.name
214
+ (!isDraggable.value ||
215
+ !dragging.value ||
216
+ draggedItem?.name === item.name) &&
217
+ e.dataTransfer
213
218
  ) {
214
219
  e.dataTransfer.dropEffect = 'none';
215
220
  return;
216
221
  }
217
222
 
223
+ if (lastDropTarget !== e.currentTarget) {
224
+ if (lastDropTarget) {
225
+ clearDropTargetClasses(lastDropTarget);
226
+ }
227
+ lastDropTarget = e.currentTarget;
228
+ }
229
+
218
230
  clearDropTargetClasses(e.currentTarget);
219
231
  addDropTargetClasses(
220
232
  e,
@@ -227,22 +239,16 @@ export function setupDraggableListOrTree(props, query, emit) {
227
239
  }
228
240
 
229
241
  /**
230
- * @param {MouseEvent} e
231
- */
232
- function dragLeave(e) {
233
- e.stopPropagation();
234
- e.preventDefault();
235
- dropPosition = null;
236
- clearDropTargetClasses(e.currentTarget);
237
- }
238
-
239
- /**
240
- * @param {MouseEvent} e
242
+ * @param {DragEvent} e
241
243
  */
242
244
  function dragEnd(e) {
243
245
  e.stopPropagation();
244
246
  dropPosition = null;
245
247
  dragging.value = false;
248
+ if (lastDropTarget) {
249
+ clearDropTargetClasses(lastDropTarget);
250
+ lastDropTarget = null;
251
+ }
246
252
  }
247
253
 
248
254
  return {
@@ -250,7 +256,6 @@ export function setupDraggableListOrTree(props, query, emit) {
250
256
  isDraggable,
251
257
  dragStart,
252
258
  dragOver,
253
- dragLeave,
254
259
  dragEnd,
255
260
  drop,
256
261
  };
@@ -272,7 +277,7 @@ function findAndSplice(
272
277
  insertPosition,
273
278
  ...itemsToInsert
274
279
  ) {
275
- const index = array.findIndex((i) => i === item);
280
+ const index = array.indexOf(item);
276
281
 
277
282
  if (index !== -1) {
278
283
  if (insertPosition === InsertMode.AFTER) {
@@ -323,3 +328,24 @@ export function moveDraggableItems(items, { item, targetItem, position }) {
323
328
  findAndSplice(items, item, 1);
324
329
  findAndSplice(items, targetItem, 0, position, item);
325
330
  }
331
+
332
+ /**
333
+ * Moves an item to a new position.
334
+ * New position is derived from a target item in the collection.
335
+ * This ensures correct movement, if rendered list is only a subset of the collection.
336
+ * @template T
337
+ * @param {import("@vcmap/core").IndexedCollection<T>} collection
338
+ * @param {import("../../components/lists/dragHelper.js").ItemMovedEvent} event
339
+ */
340
+ export function moveItem(collection, event) {
341
+ if (collection.moveTo) {
342
+ const item = collection.getByKey(event.item.name);
343
+ const target = collection.getByKey(event.targetItem.name);
344
+
345
+ const itemIndex = collection.indexOf(item);
346
+ const targetIndex = collection.indexOf(target);
347
+ const relativePosition = itemIndex < targetIndex ? -1 : 1;
348
+ const offset = relativePosition === event.position ? event.position : 0;
349
+ collection.moveTo(item, targetIndex + offset);
350
+ }
351
+ }
@@ -29,6 +29,10 @@
29
29
  import VcsHelp from '../components/notification/VcsHelp.vue';
30
30
  import VcsTreeview from '../components/lists/VcsTreeview.vue';
31
31
  import WMSGroupContentTreeItem from './wmsGroupContentTreeItem.js';
32
+ import {
33
+ moveItem,
34
+ moveDraggableItems,
35
+ } from '../components/lists/dragHelper.js';
32
36
 
33
37
  export const layerSwapId = 'layer-swap-window';
34
38
 
@@ -89,6 +93,15 @@
89
93
  name: l.name,
90
94
  title: l.properties?.title || l.name,
91
95
  index: app.layers.indexOf(l),
96
+ actions: [
97
+ {
98
+ name: 'layer-swap.delete',
99
+ icon: 'mdi-delete',
100
+ title: 'components.layerSwap.deleteButton',
101
+ callback: () => l.deactivate(),
102
+ },
103
+ ],
104
+ blockOverflow: false,
92
105
  };
93
106
  if (wmsGroupItemsMap[l.name]) {
94
107
  return {
@@ -134,16 +147,23 @@
134
147
  }
135
148
  return { into: false };
136
149
  },
137
- move({ item, targetItem }) {
150
+ /**
151
+ * @param {import("../components/lists/dragHelper.js").ItemMovedEvent} event
152
+ */
153
+ move(event) {
154
+ const { item, targetItem, position } = event;
138
155
  const layer = app.layers.getByKey(item.name);
139
156
  if (layer && !targetItem[vcsLayerName]) {
140
- app.layers.moveTo(layer, targetItem.index);
157
+ moveItem(app.layers, event);
141
158
  } else if (item[vcsLayerName] === targetItem[vcsLayerName]) {
142
159
  const wmsLayer = app.layers.getByKey(item[vcsLayerName]);
143
160
  if (wmsLayer instanceof WMSLayer) {
144
161
  const newLayerNames = wmsLayer.getLayers();
145
- newLayerNames.splice(item.index, 1);
146
- newLayerNames.splice(targetItem.index, 0, item[wmsLayerName]);
162
+ moveDraggableItems(newLayerNames, {
163
+ item: item[wmsLayerName],
164
+ targetItem: targetItem[wmsLayerName],
165
+ position,
166
+ });
147
167
  wmsLayer
148
168
  .setLayers(newLayerNames)
149
169
  .catch((e) => getLogger('LayerSwap.vue').error(e));
@@ -4,6 +4,13 @@ declare const _default: import("vue").DefineComponent<{}, {
4
4
  name: any;
5
5
  title: any;
6
6
  index: any;
7
+ actions: {
8
+ name: string;
9
+ icon: string;
10
+ title: string;
11
+ callback: () => any;
12
+ }[];
13
+ blockOverflow: boolean;
7
14
  } | {
8
15
  children: (Partial<import("./contentTreeItem.js", { with: { "resolution-mode": "import" } }).TreeViewItem> & {
9
16
  index: number;
@@ -13,14 +20,21 @@ declare const _default: import("vue").DefineComponent<{}, {
13
20
  name: any;
14
21
  title: any;
15
22
  index: any;
23
+ actions: {
24
+ name: string;
25
+ icon: string;
26
+ title: string;
27
+ callback: () => any;
28
+ }[];
29
+ blockOverflow: boolean;
16
30
  })[]>;
17
31
  dropTargetZones(item: any, targetItem: any): false | {
18
32
  into: boolean;
19
33
  };
20
- move({ item, targetItem }: {
21
- item: any;
22
- targetItem: any;
23
- }): void;
34
+ /**
35
+ * @param {import("../components/lists/dragHelper.js").ItemMovedEvent} event
36
+ */
37
+ move(event: import("../components/lists/dragHelper.js").ItemMovedEvent): void;
24
38
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
25
39
  export default _default;
26
40
  declare const wmsLayerName: unique symbol;