2024-04-18 10:52:45 +02:00
|
|
|
<script lang="ts">
|
2024-04-22 11:38:23 +02:00
|
|
|
import { fileOrder, files, selectedFiles, selectFiles } from '$lib/stores';
|
2024-04-18 10:52:45 +02:00
|
|
|
|
2024-04-20 18:47:16 +02:00
|
|
|
import { ScrollArea } from '$lib/components/ui/scroll-area/index';
|
2024-04-19 17:06:36 +02:00
|
|
|
|
2024-04-20 18:47:16 +02:00
|
|
|
import Sortable from 'sortablejs/Sortable';
|
|
|
|
|
|
|
|
import { onMount, tick } from 'svelte';
|
|
|
|
import type { GPXFile } from 'gpx';
|
2024-04-19 17:06:36 +02:00
|
|
|
|
|
|
|
let tabs: HTMLDivElement;
|
2024-04-20 18:47:16 +02:00
|
|
|
let buttons: HTMLButtonElement[] = [];
|
|
|
|
let sortable: Sortable;
|
|
|
|
|
|
|
|
function selectFile(file: GPXFile) {
|
|
|
|
selectedFiles.update((selectedFiles) => {
|
|
|
|
selectedFiles.clear();
|
|
|
|
selectedFiles.add(file);
|
|
|
|
return selectedFiles;
|
|
|
|
});
|
|
|
|
}
|
2024-04-19 17:06:36 +02:00
|
|
|
|
2024-04-20 18:47:16 +02:00
|
|
|
function addSelectFile(file: GPXFile) {
|
|
|
|
selectedFiles.update((selectedFiles) => {
|
|
|
|
selectedFiles.add(file);
|
|
|
|
return selectedFiles;
|
|
|
|
});
|
|
|
|
}
|
2024-04-20 15:38:17 +02:00
|
|
|
|
2024-04-20 18:47:16 +02:00
|
|
|
function deselectFile(file: GPXFile) {
|
|
|
|
selectedFiles.update((selectedFiles) => {
|
|
|
|
selectedFiles.delete(file);
|
|
|
|
return selectedFiles;
|
|
|
|
});
|
|
|
|
}
|
2024-04-20 15:38:17 +02:00
|
|
|
|
2024-04-20 18:47:16 +02:00
|
|
|
onMount(() => {
|
|
|
|
sortable = Sortable.create(tabs, {
|
2024-04-20 15:38:17 +02:00
|
|
|
forceAutoScrollFallback: true,
|
|
|
|
multiDrag: true,
|
2024-04-20 18:47:16 +02:00
|
|
|
multiDragKey: 'shift',
|
|
|
|
selectedClass: 'sortable-selected',
|
|
|
|
avoidImplicitDeselect: true,
|
|
|
|
onSelect: (e) => {
|
|
|
|
const index = parseInt(e.item.getAttribute('data-id'));
|
|
|
|
addSelectFile($files[index]);
|
2024-04-20 18:55:40 +02:00
|
|
|
if (!e.originalEvent.shiftKey && $selectedFiles.size > 1) {
|
|
|
|
$selectedFiles.forEach((file) => {
|
|
|
|
if (file !== $files[index]) {
|
|
|
|
deselectFile(file);
|
|
|
|
const index = $files.indexOf(file);
|
|
|
|
Sortable.utils.deselect(buttons[index]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2024-04-20 18:47:16 +02:00
|
|
|
},
|
|
|
|
onDeselect: (e) => {
|
|
|
|
const index = parseInt(e.item.getAttribute('data-id'));
|
|
|
|
deselectFile($files[index]);
|
2024-04-22 11:38:23 +02:00
|
|
|
},
|
|
|
|
onSort: () => {
|
|
|
|
$fileOrder = sortable.toArray().map((index) => $files[parseInt(index)]);
|
2024-04-20 18:47:16 +02:00
|
|
|
}
|
2024-04-19 17:06:36 +02:00
|
|
|
});
|
|
|
|
});
|
2024-04-20 18:47:16 +02:00
|
|
|
|
|
|
|
selectFiles.update(() => {
|
|
|
|
return {
|
|
|
|
select: (file: GPXFile) => {
|
|
|
|
buttons.forEach((button) => {
|
|
|
|
if (button) {
|
|
|
|
Sortable.utils.deselect(button);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const index = $files.indexOf(file);
|
|
|
|
Sortable.utils.select(buttons[index]);
|
|
|
|
selectFile(file);
|
|
|
|
},
|
|
|
|
addSelect: (file: GPXFile) => {
|
|
|
|
const index = $files.indexOf(file);
|
|
|
|
Sortable.utils.select(buttons[index]);
|
|
|
|
addSelectFile(file);
|
|
|
|
},
|
|
|
|
removeSelect: (file: GPXFile) => {
|
|
|
|
const index = $files.indexOf(file);
|
|
|
|
Sortable.utils.deselect(buttons[index]);
|
|
|
|
deselectFile(file);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
2024-04-18 10:52:45 +02:00
|
|
|
</script>
|
|
|
|
|
2024-04-19 17:06:36 +02:00
|
|
|
<div class="absolute h-10 -translate-y-10 w-fit max-w-full bg-secondary rounded-t">
|
2024-04-19 16:13:08 +02:00
|
|
|
<ScrollArea orientation="horizontal" class="w-full h-full" scrollbarXClasses="h-2">
|
2024-04-19 17:06:36 +02:00
|
|
|
<div bind:this={tabs} class="flex flex-row gap-1">
|
2024-04-20 18:47:16 +02:00
|
|
|
{#each $files as file, index}
|
2024-04-19 16:13:08 +02:00
|
|
|
<button
|
2024-04-20 18:47:16 +02:00
|
|
|
bind:this={buttons[index]}
|
|
|
|
data-id={index}
|
|
|
|
class="my-1 px-1.5 py-1 rounded bg-secondary hover:bg-gray-200 shadow-none first:ml-1 last:mr-1"
|
2024-04-18 15:30:19 +02:00
|
|
|
>
|
|
|
|
{file.metadata.name}
|
2024-04-19 16:13:08 +02:00
|
|
|
</button>
|
2024-04-18 15:30:19 +02:00
|
|
|
{/each}
|
|
|
|
</div>
|
|
|
|
</ScrollArea>
|
|
|
|
</div>
|
2024-04-20 18:47:16 +02:00
|
|
|
|
|
|
|
<style lang="postcss">
|
|
|
|
div :global(.sortable-selected) {
|
|
|
|
@apply bg-background shadow;
|
|
|
|
}
|
|
|
|
</style>
|