diff --git a/website/package-lock.json b/website/package-lock.json index c2922f40..5a8c583d 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -62,6 +62,7 @@ "prettier-plugin-svelte": "^3.4.0", "svelte": "^5.33.18", "svelte-check": "^4.0.0", + "svelte-dnd-action": "^0.9.65", "svelte-sonner": "^1.0.5", "tailwind-variants": "^3.1.1", "tailwindcss": "^4.1.8", @@ -8242,6 +8243,16 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/svelte-dnd-action": { + "version": "0.9.65", + "resolved": "https://registry.npmjs.org/svelte-dnd-action/-/svelte-dnd-action-0.9.65.tgz", + "integrity": "sha512-GKFtrAtYAjcm27aMELoXOhkLtKA1AEoj2njjCReCer6jh1hnRtTHdEO4Kjfpayz+ZAvE0MMwIvLISW3tsiO9Qg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "svelte": ">=3.23.0 || ^5.0.0-next.0" + } + }, "node_modules/svelte-eslint-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.2.0.tgz", diff --git a/website/package.json b/website/package.json index 3da597c7..b52597d8 100644 --- a/website/package.json +++ b/website/package.json @@ -46,6 +46,7 @@ "prettier-plugin-svelte": "^3.4.0", "svelte": "^5.33.18", "svelte-check": "^4.0.0", + "svelte-dnd-action": "^0.9.65", "svelte-sonner": "^1.0.5", "tailwind-variants": "^3.1.1", "tailwindcss": "^4.1.8", diff --git a/website/src/lib/components/map/layer-control/CustomLayers.svelte b/website/src/lib/components/map/layer-control/CustomLayers.svelte index 6de2ca1a..c76eddbd 100644 --- a/website/src/lib/components/map/layer-control/CustomLayers.svelte +++ b/website/src/lib/components/map/layer-control/CustomLayers.svelte @@ -19,11 +19,11 @@ } from '@lucide/svelte'; import { i18n } from '$lib/i18n.svelte'; import { defaultBasemap, type CustomLayer } from '$lib/assets/layers'; - import { onDestroy, onMount } from 'svelte'; - import Sortable from 'sortablejs/Sortable'; + import { onMount } from 'svelte'; import { customBasemapUpdate } from './utils'; import { settings } from '$lib/logic/settings'; import { map } from '$lib/components/map/map'; + import { dndzone } from 'svelte-dnd-action'; const { customLayers, @@ -55,12 +55,6 @@ let selectedLayerId: string | undefined = $state(undefined); - let basemapContainer: HTMLElement; - let overlayContainer: HTMLElement; - - let basemapSortable: Sortable; - let overlaySortable: Sortable; - onMount(() => { if ($customBasemapOrder.length === 0) { $customBasemapOrder = Object.keys($customLayers).filter( @@ -72,34 +66,26 @@ (id) => $customLayers[id].layerType === 'overlay' ); } - - basemapSortable = Sortable.create(basemapContainer, { - onSort: (e) => { - $customBasemapOrder = basemapSortable.toArray(); - $selectedBasemapTree.basemaps['custom'] = $customBasemapOrder.reduce((acc, id) => { - acc[id] = true; - return acc; - }, {}); - }, - }); - overlaySortable = Sortable.create(overlayContainer, { - onSort: (e) => { - $customOverlayOrder = overlaySortable.toArray(); - $selectedOverlayTree.overlays['custom'] = $customOverlayOrder.reduce((acc, id) => { - acc[id] = true; - return acc; - }, {}); - }, - }); - - basemapSortable.sort($customBasemapOrder); - overlaySortable.sort($customOverlayOrder); }); - onDestroy(() => { - basemapSortable.destroy(); - overlaySortable.destroy(); - }); + let customBasemapItems: { + id: string; + name: string; + }[] = $derived( + $customBasemapOrder.map((id) => ({ + id: id, + name: $customLayers[id].name, + })) + ); + let customOverlayItems: { + id: string; + name: string; + }[] = $derived( + $customOverlayOrder.map((id) => ({ + id: id, + name: $customLayers[id].name, + })) + ); $effect(() => { setDataFromSelectedLayer(selectedLayerId); @@ -306,17 +292,37 @@ {/if}
{ + if (element) { + element.style.opacity = '0.5'; + } + }, + }} + onconsider={(e) => { + customBasemapItems = e.detail.items; + }} + onfinalize={(e) => { + customBasemapItems = e.detail.items; + $customBasemapOrder = customBasemapItems.map((item) => item.id); + $selectedBasemapTree.basemaps['custom'] = customBasemapItems.reduce((acc, item) => { + acc[item.id] = true; + return acc; + }, {}); + }} > - {#each $customBasemapOrder as id (id)} -
+ {#each customBasemapItems as item (item.id)} +
- {$customLayers[id].name} + {item.name}
{/if}
{ + if (element) { + element.style.opacity = '0.5'; + } + }, + }} + onconsider={(e) => { + customOverlayItems = e.detail.items; + }} + onfinalize={(e) => { + customOverlayItems = e.detail.items; + $customOverlayOrder = customOverlayItems.map((item) => item.id); + $selectedOverlayTree.overlays['custom'] = customOverlayItems.reduce((acc, item) => { + acc[item.id] = true; + return acc; + }, {}); + }} > - {#each $customOverlayOrder as id (id)} -
+ {#each customOverlayItems as item (item.id)} +
- {$customLayers[id].name} + {item.name}