import type { BlobUploadStrategy, PreviewableUploadingFile, UploadPreviewMode, UploadingFile } from './upload-types'; type SuccessfulUpload = Extract; type FailedUpload = Extract; export type AddOptions = { /** Stage an object URL for local preview. @default 'never' */ preview?: UploadPreviewMode; }; export type UploadOutcome = { /** Files whose upload ended in error, at the moment this call settled. */ failed: FailedUpload[]; /** Files that reached `success`. */ succeeded: SuccessfulUpload[]; }; export type UploadMediaStoreOptions = { /** * Auto-resize images before upload. Pass `false` to disable; pass an object to override the * defaults. `max1` / `max2` are not tied to width / height — the longer side is matched to * the larger limit. @default `{ max1: 1600, max2: 1000 }` */ resize?: { max1: number; max2: number; } | false; /** Parallel upload limit. @default 20 */ concurrency?: number; on?: { /** Fires per file once its presigned URL is allocated and the blob is uploaded. */ blobId?: (file: SuccessfulUpload, blobId: string) => void; /** Fires per file when the upload errors out. */ error?: (file: FailedUpload, error: unknown) => void; /** Fires once after all queued files have either succeeded or errored. */ done?: () => void; }; }; /** * Queue-and-upload coordinator. Pure logic — no UI. Pair with `FileRow` / `FileUploadProgress` * for visual progress, both of which consume the `files: UploadingFile[]` array reactively. * * Lifecycle: * 1. `add(file)` — push raw `File` into the queue (`status: 'queued'`). * 2. `upload()` — fetch presigned URLs from the strategy, then PUT each blob in parallel. * Per-file status flows `queued → uploading → success | error`; `progress` updates as * bytes are sent. * 3. Consumer wires `on.blobId` to capture each blob ID for form state, or reads `files[i].blobId`. * * @example * ```ts * const store = new UploadMediaStore(uploadStrategy, { * on: { blobId: (f, id) => { avatarBlobId = id; } } * }); * store.add(rawFile); * const { failed } = await store.upload(); * if (failed.length > 0) { ... } * ``` */ export declare class UploadMediaStore { private _files; private _inFlight; private _nextRunId; private _strategy; private opts; constructor(strategy: BlobUploadStrategy, opts?: UploadMediaStoreOptions); /** Reactive read of the queue. */ get files(): UploadingFile[]; /** * Append a raw `File`, returns its `UploadingFile` wrapper with a stable `id`. Pass * `{ preview: 'always' }` when the caller knows this file gets previewed — the returned wrapper is * then typed with a non-null `previewUrl`. The wrapper is a snapshot: `previewUrl` never changes, * but read `status` / `progress` back from `files` rather than from it. * * `'always'` is the only mode that narrows the type — `'mime'` resolves against `file.type` at * runtime, so its `previewUrl` stays `string | null` however previewable the file looks. */ add(file: File, options: AddOptions & { preview: 'always'; }): PreviewableUploadingFile; add(file: File, options?: AddOptions): UploadingFile; /** Append multiple raw files at once, with the same `preview` semantics as `add()` — only `'always'` narrows the returned type. */ addMany(files: File[], options: AddOptions & { preview: 'always'; }): PreviewableUploadingFile[]; addMany(files: File[], options?: AddOptions): UploadingFile[]; /** Remove a file from the queue by its `UploadingFile.id`, revoking its `previewUrl`. Does NOT cancel an in-flight upload. */ remove(id: string): void; /** Clear all queued / completed files, revoking their `previewUrl`s. Does NOT cancel any in-flight uploads. */ clear(): void; /** Resolved blob for a file id — `null` while it is still queued / uploading, or if it failed. */ resolve(id: string): { blobId: string; readUrl: string; } | null; /** * Run the upload pipeline for every file currently in `'queued'` status. Files already * `uploading` / `success` / `error` are skipped. Resolves once **every** run of this store — * including ones started by earlier `upload()` calls — has reached a terminal status, so * `await store.upload()` always means "nothing of mine is in flight any more". Each run registers * itself in `AppUploadActivity` for its duration, so a mounted `UploadProgressToaster` picks it up * with no extra wiring. */ upload(): Promise; private outcome; private settled; private runQueued; private maybeResize; private fail; private failAll; private transition; } export {};