Media Provider
Interface
Section titled “Interface”interface MediaProvider { list(opts: { cursor?: string search?: string signal?: AbortSignal }): Promise<{ items: MediaItem[]; nextCursor?: string }>
upload( file: File, opts?: { signal?: AbortSignal; onProgress?: (pct: number) => void }, ): Promise<MediaItem>}
interface MediaItem { id: string url: string thumbnailUrl?: string width?: number height?: number name?: string mimeType?: string}Default
Section titled “Default”createNullMediaProvider() — returns an empty list and rejects uploads. Use
this if you don’t need a media library.
Example: REST backend
Section titled “Example: REST backend”import type { MediaProvider } from '@fastlabai/design-editor'
export function createMyMediaProvider(): MediaProvider { return { async list({ cursor, search, signal }) { const r = await fetch( `/api/media?cursor=${cursor ?? ''}&q=${search ?? ''}`, { signal }, ) return r.json() }, async upload(file, { onProgress } = {}) { const fd = new FormData() fd.append('file', file) const r = await fetch('/api/media', { method: 'POST', body: fd }) onProgress?.(100) return r.json() }, }}Pass it to the editor:
<DesignEditor mediaProvider={createMyMediaProvider()} />Best Practice: 3-Tier Caching Architecture
Section titled “Best Practice: 3-Tier Caching Architecture”For production applications dealing with high-res images and videos, we strongly recommend implementing a Memory → IndexedDB → Cloud pipeline. This provides instant zero-latency UI updates while safely uploading large files in the background without crashing the browser’s localStorage (which is limited to ~5MB).
Here is a conceptual example using the lightweight idb-keyval library for IndexedDB:
import { get, set } from 'idb-keyval'import type { MediaProvider } from '@fastlabai/design-editor'
export const advancedMediaProvider: MediaProvider = { list: async () => { // Load previously uploaded items from local IndexedDB const cached = (await get('my_local_media')) || []
// Regenerate Object URLs for instant preview const items = cached.map(item => ({ ...item, url: URL.createObjectURL(item.file) }))
return { items } },
upload: async (file: File) => { // 1. Memory (Fast Preview): Create a local blob URL instantly const url = URL.createObjectURL(file) const item = { id: Date.now().toString(), url, name: file.name, mimeType: file.type }
// 2. IndexedDB (Persistent Cache): Save binary blob to browser storage const cached = (await get('my_local_media')) || [] await set('my_local_media', [{ ...item, file }, ...cached])
// 3. Cloud (Background Upload): Send to S3/CDN asynchronously // uploadToS3(file).then(realUrl => updateItem(item.id, realUrl))
return item }}