Preview
API
<FilePreview> reference. For motivation and design rationale, see Design.
<FilePreview> props
import { FilePreview } from '@vuer-ai/vuer-m3u/preview'| Prop | Type | Default | Description |
|---|---|---|---|
url | string | — (required) | Source URL. Used as the fetch target and, when filename is unset, as the basis for kind resolution. |
filename | string | derived from url | Display name and kind-resolution input. Set this when url is opaque (e.g. pre-signed S3 with no extension in the path). |
size | number | undefined | Byte size from a listing API. Skips the HEAD probe entirely. |
contentType | string | undefined | MIME type from a listing API. Used as a fallback when extension lookup is ambiguous. |
fetcher | (url: string, init?: RequestInit) => Promise<Response> | globalThis.fetch | Override for fetch. Useful for adding auth headers — see Recipes. |
limits | Partial<PreviewLimits> | see below | Per-kind size limits. Merged with defaults. |
probe | 'never' | 'auto' | 'always' | 'never' | When to issue a HEAD request. 'auto' only probes if both size and contentType are missing. |
onDownload | (meta: ResolvedFileMeta) => void | — | Called when the user clicks the download button. Use this to swap in a pre-signed URL. |
className | string | — | Class on the outer wrapper. |
accentColor | string | 'rgb(var(--color-accent))' | CSS color for active states (header borders, focus rings). |
PreviewLimits
interface PreviewLimits {
imageMaxBytes: number // default: 20 * 1024 * 1024 (20 MB, hard)
textMaxBytes: number // default: 5 * 1024 * 1024 (5 MB, soft)
markdownMaxBytes: number // default: 5 * 1024 * 1024 (5 MB, soft)
codeMaxBytes: number // default: 5 * 1024 * 1024 (5 MB, soft)
csvMaxBytes: number // default: 10 * 1024 * 1024 (10 MB, soft)
jsonlMaxBytes: number // default: 10 * 1024 * 1024 (10 MB, soft)
npyPreviewElements: number // default: 1024 (elements, not bytes)
}limits is Partial<PreviewLimits> — only override what you need:
<FilePreview url={url} limits={{ csvMaxBytes: 50 * 1024 * 1024 }} />See Size Strategy for the hard-vs-soft semantics.
ResolvedFileMeta
What the previewers see after resolution. You receive this in onDownload:
interface ResolvedFileMeta {
url: string
filename: string
kind: PreviewKind
size?: number // bytes, if known
contentType?: string // MIME, if known
extension: string // lowercase, no dot, e.g. "png"
}PreviewKind
type PreviewKind =
| 'image'
| 'video'
| 'audio'
| 'text'
| 'code'
| 'markdown'
| 'csv'
| 'tsv'
| 'jsonl'
| 'npy'
| 'mcap'
| 'unsupported'Resolution order: filename extension → contentType MIME prefix (image/* → 'image', video/* → 'video', etc.) → 'unsupported'.
Error states
The preview surface always renders something — never null. The error states are:
| State | Trigger | Renders |
|---|---|---|
| Loading | Fetch in flight, decoder running | Spinner with filename |
| Too large | Image over imageMaxBytes | "File too large" placeholder + download button |
| Truncated | Soft-limit hit on text/code/md/csv/jsonl | Banner: "Showing first N MB of M MB" + content |
| Network error | fetch rejected, non-2xx response | Error card with message + retry button |
| Parse error | Decoder threw (malformed NPY, MCAP, etc.) | Error card + download fallback |
| Unsupported | Kind resolved to 'unsupported' | Generic file card + download button |
Each error card preserves the header bar so the user can always download the original.
Imports summary
import {
FilePreview,
type PreviewLimits,
type ResolvedFileMeta,
type PreviewKind,
} from '@vuer-ai/vuer-m3u/preview'