subdocument-splitting-plan

This commit is contained in:
rehlert committed 2026-10-06 22:52:35 +02:00
1 parent f09384d2e6
commit ca06ca2050
47 files changed
+4097 -136

No files matched your search

+89 -18
View File
@@ -1,4 +1,5 @@
<script lang="ts">
import AttachmentMenu, { type AttachmentMoveTarget } from '$lib/components/AttachmentMenu.svelte';
import AttachmentPreview from '$lib/components/AttachmentPreview.svelte';
import Button from '$lib/components/ui/button.svelte';
import type { AttachmentLocation, SubDocument, ZipAttachment } from '$lib/zip-processing';
@@ -10,6 +11,15 @@
thumbnailWidth: number;
isBlockDragSource?: boolean;
isBlockDropTarget?: boolean;
groupingMode?: boolean;
selectedPaths?: Set<string>;
onToggleSelection?: (path: string) => void;
autoFocusName?: boolean;
moveTargets?: AttachmentMoveTarget[];
onMoveToTarget?: (path: string, targetId: string) => void;
onMoveToLoose?: (path: string) => void;
onSplit?: (attachment: ZipAttachment) => void;
onRemoveAttachment?: (attachment: ZipAttachment) => void;
onSubDocumentChange?: (next: SubDocument) => void;
onRemove?: () => void;
onAttachmentMove?: (source: AttachmentLocation, target: AttachmentLocation) => void;
@@ -28,6 +38,15 @@
thumbnailWidth = 200,
isBlockDragSource = false,
isBlockDropTarget = false,
groupingMode = false,
selectedPaths = new Set<string>(),
onToggleSelection = () => {},
autoFocusName = false,
moveTargets = [],
onMoveToTarget = () => {},
onMoveToLoose = () => {},
onSplit = () => {},
onRemoveAttachment = () => {},
onSubDocumentChange = () => {},
onRemove = () => {},
onAttachmentMove = () => {},
@@ -40,6 +59,7 @@
downloadDisabled = false
}: Props = $props();
let nameInput = $state<HTMLInputElement | null>(null);
let subDocumentName = $state('');
let dragIndex = $state<number | null>(null);
let dropIndex = $state<number | null>(null);
@@ -48,6 +68,14 @@
subDocumentName = subDocument.name;
});
$effect(() => {
if (autoFocusName && nameInput) {
nameInput.focus();
nameInput.select();
nameInput.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
}
});
const emitChange = (overrides: Partial<SubDocument> = {}) => {
onSubDocumentChange({
...subDocument,
@@ -81,6 +109,11 @@
};
const handleCardDragStart = (index: number, event: DragEvent) => {
if (groupingMode) {
event.preventDefault();
return;
}
dragIndex = index;
dropIndex = index;
@@ -195,6 +228,7 @@
<label class="block min-w-0 flex-1">
<span class="sr-only">Teildokumentname</span>
<input
bind:this={nameInput}
class="w-full max-w-md rounded-md border border-primary-200 bg-white px-3 py-1.5 text-[15px] font-semibold text-primary-900 outline-none transition focus:border-primary-400 focus:ring-2 focus:ring-primary-200"
type="text"
value={subDocumentName}
@@ -272,33 +306,70 @@
dropIndex === index
? 'border-primary-400 ring-1 ring-primary-200'
: 'border-primary-100',
dragIndex === index ? 'opacity-60' : ''
dragIndex === index ? 'opacity-60' : '',
groupingMode && selectedPaths.has(attachment.path)
? 'border-primary-500 ring-2 ring-primary-300'
: ''
)}
style={`width: ${thumbnailWidth}px;`}
draggable="true"
draggable={groupingMode ? 'false' : 'true'}
ondragstart={(event) => handleCardDragStart(index, event)}
ondragover={(event) => handleCardDragOver(index, event)}
ondrop={(event) => handleCardDrop(index, event)}
ondragend={handleCardDragEnd}
>
<div class="flex min-w-0 flex-1 flex-row items-baseline gap-2 py-1">
<button
class="w-fit cursor-grab rounded-md border border-primary-200 bg-white px-2 py-1 text-sm font-semibold leading-none text-primary-700 active:cursor-grabbing"
draggable="false"
type="button"
aria-label="Datei verschieben"
>
::
</button>
{#if groupingMode}
<label class="flex cursor-pointer flex-col gap-2">
<div class="flex items-center gap-2 px-1 text-[13px] font-medium text-primary-900">
<input
class="h-4 w-4 accent-primary-700"
type="checkbox"
checked={selectedPaths.has(attachment.path)}
onchange={() => onToggleSelection(attachment.path)}
/>
<span class="truncate"
>{selectedPaths.has(attachment.path) ? 'Ausgewählt' : 'Auswählen'}</span
>
</div>
<div
class="truncate text-[13px] font-medium leading-tight text-primary-900"
title={attachment.name}
>
{attachment.name}
<div
class="truncate text-[13px] font-medium leading-tight text-primary-900"
title={attachment.name}
>
{attachment.name}
</div>
<AttachmentPreview {attachment} />
</label>
{:else}
<div class="flex min-w-0 flex-1 flex-row items-center gap-1 py-1">
<button
class="w-fit cursor-grab rounded-md border border-primary-200 bg-white px-2 py-1 text-sm font-semibold leading-none text-primary-700 active:cursor-grabbing"
draggable="false"
type="button"
aria-label="Datei verschieben"
>
::
</button>
<div
class="min-w-0 flex-1 truncate text-[13px] font-medium leading-tight text-primary-900"
title={attachment.name}
>
{attachment.name}
</div>
<AttachmentMenu
{attachment}
{moveTargets}
canSplit={attachment.kind === 'pdf'}
onMoveToTarget={(targetId) => onMoveToTarget(attachment.path, targetId)}
onMoveToLoose={() => onMoveToLoose(attachment.path)}
onSplit={() => onSplit(attachment)}
onRemove={() => onRemoveAttachment(attachment)}
/>
</div>
</div>
<AttachmentPreview {attachment} />
<AttachmentPreview {attachment} />
{/if}
</li>
{/each}
</ul>