101 lines
3.0 KiB
Svelte
101 lines
3.0 KiB
Svelte
<script lang="ts">
|
|
import { File, Folder, FolderPlus, MoreHorizontal, Scissors, Trash2 } from '@lucide/svelte';
|
|
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
|
|
import type { ZipAttachment } from '$lib/zip-processing';
|
|
|
|
export type AttachmentMoveTarget = {
|
|
id: string;
|
|
name: string;
|
|
};
|
|
|
|
type Props = {
|
|
attachment: ZipAttachment;
|
|
/** Existing sub-document move targets (excluding the attachment's own). */
|
|
moveTargets: AttachmentMoveTarget[];
|
|
canSplit?: boolean;
|
|
onMoveToTarget: (targetId: string) => void;
|
|
onMoveToLoose?: () => void;
|
|
onSplit?: () => void;
|
|
onRemove?: () => void;
|
|
};
|
|
|
|
let {
|
|
attachment,
|
|
moveTargets,
|
|
canSplit = false,
|
|
onMoveToTarget,
|
|
onMoveToLoose,
|
|
onSplit,
|
|
onRemove
|
|
}: Props = $props();
|
|
</script>
|
|
|
|
<DropdownMenu.Root>
|
|
<DropdownMenu.Trigger aria-label={`Aktionen für ${attachment.name}`}>
|
|
{#snippet child({ props })}
|
|
<button
|
|
{...props}
|
|
type="button"
|
|
class="flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-md border border-primary-200 bg-white text-primary-700 transition hover:border-primary-400 hover:bg-primary-50 focus-visible:ring-2 focus-visible:ring-primary-300"
|
|
aria-label={`Aktionen für ${attachment.name}`}
|
|
data-attachment-menu={attachment.path}
|
|
draggable="false"
|
|
ondragstart={(event) => event.preventDefault()}
|
|
>
|
|
<MoreHorizontal class="size-3.5" aria-hidden="true" />
|
|
</button>
|
|
{/snippet}
|
|
</DropdownMenu.Trigger>
|
|
|
|
<DropdownMenu.Content align="end" side="top" sideOffset={6} class="w-56">
|
|
<DropdownMenu.Group>
|
|
<DropdownMenu.GroupHeading>Verschieben</DropdownMenu.GroupHeading>
|
|
|
|
{#each moveTargets as target (target.id)}
|
|
<DropdownMenu.Item
|
|
aria-label={`Nach „${target.name}“ verschieben`}
|
|
onclick={() => onMoveToTarget(target.id)}
|
|
>
|
|
<Folder aria-hidden="true" />
|
|
<span class="truncate">{target.name}</span>
|
|
</DropdownMenu.Item>
|
|
{/each}
|
|
|
|
<DropdownMenu.Item
|
|
aria-label="In neues Teildokument verschieben"
|
|
onclick={() => onMoveToTarget('new')}
|
|
>
|
|
<FolderPlus aria-hidden="true" />
|
|
<span class="truncate">Neues Teildokument</span>
|
|
</DropdownMenu.Item>
|
|
|
|
{#if onMoveToLoose}
|
|
<DropdownMenu.Item aria-label="Zu den losen Dateien verschieben" onclick={onMoveToLoose}>
|
|
<File aria-hidden="true" />
|
|
<span class="truncate">Zu den losen Dateien</span>
|
|
</DropdownMenu.Item>
|
|
{/if}
|
|
</DropdownMenu.Group>
|
|
|
|
{#if canSplit && onSplit}
|
|
<DropdownMenu.Separator />
|
|
<DropdownMenu.Item aria-label={`Teilen: ${attachment.name}`} onclick={onSplit}>
|
|
<Scissors aria-hidden="true" />
|
|
<span class="truncate">Teilen…</span>
|
|
</DropdownMenu.Item>
|
|
{/if}
|
|
|
|
{#if onRemove}
|
|
<DropdownMenu.Separator />
|
|
<DropdownMenu.Item
|
|
variant="destructive"
|
|
onclick={onRemove}
|
|
aria-label={`Entfernen: ${attachment.name}`}
|
|
>
|
|
<Trash2 aria-hidden="true" />
|
|
<span class="truncate">Entfernen</span>
|
|
</DropdownMenu.Item>
|
|
{/if}
|
|
</DropdownMenu.Content>
|
|
</DropdownMenu.Root>
|