feat: flow for multiple files - pipeline, tools

This commit is contained in:
2026-10-09 20:23:14 +05:00
parent 0cb94d06c2
commit bac82f8442
15 changed files with 648 additions and 193 deletions
@@ -2,33 +2,45 @@
import { toDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types";
import { t } from "$lib/i18n/t";
import type { InputMode } from "$lib/registry";
import type { InputMode, ToolImageFile } from "$lib/registry";
import Dropzone from "./Dropzone.svelte";
import PartsGrid from "./PartsGrid.svelte";
import PreviewTile from "./PreviewTile.svelte";
import SchemaTextSource from "./SchemaTextSource.svelte";
interface Props {
mode: InputMode;
source: PixelImage | null;
sources?: ToolImageFile[];
textSource?: string;
running?: boolean;
fileCount?: number;
ontextinput?: (text: string) => void;
onrendertext?: () => void;
onupload?: (file: File) => void;
onuploadmany?: (files: File[]) => void;
}
let {
mode,
source,
sources = [],
textSource = "",
running = false,
fileCount = 0,
ontextinput,
onrendertext,
onupload,
onuploadmany,
}: Props = $props();
const sourceUrl = $derived(source ? toDataUrl(source) : null);
const sourceDims = $derived(
source ? `${source.width} × ${source.height}` : undefined,
source
? `${source.width} × ${source.height}` +
(fileCount > 1
? ` · ${t("sourceCard.countFiles", { count: fileCount })}`
: "")
: undefined,
);
let dragging = $state(false);
@@ -57,8 +69,13 @@
function onDrop(e: DragEvent) {
e.preventDefault();
dragging = false;
const file = e.dataTransfer?.files?.[0];
if (file) onupload?.(file);
pickFiles(Array.from(e.dataTransfer?.files ?? []));
}
function pickFiles(files: File[]) {
if (files.length === 0) return;
if (files.length > 1 && onuploadmany) onuploadmany(files);
else if (files[0]) onupload?.(files[0]);
}
function open() {
@@ -106,17 +123,21 @@
bind:this={input}
type="file"
accept="image/*"
multiple
hidden
onchange={(e) => {
const file = (e.target as HTMLInputElement).files?.[0];
if (file) onupload?.(file);
pickFiles(Array.from((e.target as HTMLInputElement).files ?? []));
}}
/>
<img
data-testid="source-image"
src={sourceUrl}
alt={t("sourceCard.alt")}
/>
{#if sources.length > 1}
<PartsGrid files={sources} />
{:else}
<img
data-testid="source-image"
src={sourceUrl}
alt={t("sourceCard.alt")}
/>
{/if}
{#if dragging}
<span class="drop-hint">{t("dropZone.overlayDefault")}</span>
{:else}
@@ -124,7 +145,7 @@
{/if}
</div>
{:else if mode === "image"}
<Dropzone onfile={onupload} />
<Dropzone onfile={onupload} onfiles={onuploadmany} />
{:else}
<span class="empty">{t("sourceCard.noSource")}</span>
{/if}