File List
files-sdk/file-listFreeComponent
Reactive list of stored files with thumbnails, download and delete.
Install it
npx shadcn@latest add https://files-sdk.dev/r/file-list.jsonSource
1"use client";23import type { StoredFile } from "files-sdk";4import type { UseFilesResult } from "files-sdk/react";5import {6 DownloadIcon,7 FileIcon,8 Loader2Icon,9 RefreshCwIcon,10 Trash2Icon,11} from "lucide-react";12import { useCallback, useEffect, useRef, useState } from "react";1314import { Button } from "@/components/ui/button";15import { cn } from "@/lib/utils";1617export interface FileListProps {18 /** A `useFiles()` instance — lists, downloads and deletes through it. */19 files: UseFilesResult;20 /** Only show keys under this prefix (folder), e.g. `"docs/"`. */21 prefix?: string;22 /** Endpoint for inline image thumbnails (the gateway download proxy). Default `"/api/files"`. */23 endpoint?: string;24 /** Hide the delete action. */25 readOnly?: boolean;26 /** Called when a file row is clicked. Rows are inert without it. */27 onSelect?: (file: StoredFile) => void;28 /** Called after a successful delete. */29 onChanged?: () => void;30 className?: string;31}3233const formatBytes = (bytes: number): string => {34 if (bytes === 0) {35 return "0 B";36 }37 const units = ["B", "KB", "MB", "GB", "TB"];38 const exponent = Math.min(39 Math.floor(Math.log(bytes) / Math.log(1024)),40 units.length - 141 );42 return `${(bytes / 1024 ** exponent).toFixed(exponent === 0 ? 0 : 1)} ${units[exponent]}`;43};4445const Thumbnail = ({46 canSign,47 endpoint,48 file,49 filesRef,50}: {51 canSign: boolean | undefined;52 endpoint: string;53 file: StoredFile;54 filesRef: { current: UseFilesResult };55}) => {56 const [src, setSrc] = useState<string>();57 const [failed, setFailed] = useState(false);58 const isImage = file.type.startsWith("image/");5960 useEffect(() => {61 if (!isImage || canSign === undefined) {62 return;63 }64 // Prefer a signed/direct URL when the adapter can mint one — some dev65 // servers (e.g. TanStack Start's nitro dev middleware) treat any66 // `Sec-Fetch-Dest: image` request to a catch-all route as a static asset67 // and 404 it before the gateway runs, so an <img> pointed at the download68 // proxy never loads there. Fall back to the proxy, which works on every69 // adapter — even ones that can't sign.70 const proxy = `${endpoint}${endpoint.includes("?") ? "&" : "?"}op=download&key=${encodeURIComponent(file.key)}`;71 if (!canSign) {72 setSrc(proxy);73 return;74 }75 let cancelled = false;76 const resolve = async () => {77 let next = proxy;78 try {79 next = await filesRef.current.url(file.key);80// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from files-sdk
All 12 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Capabilities Badgescapabilities-badges | files-sdk | Components | Free | 2 deps | |
| Dropzonedropzone | files-sdk | Components | Free | 2 deps | |
| File Actionsfile-actions | files-sdk | Components | Free | 2 deps | |
| File Browserfile-browser | files-sdk | Components | Free | 2 deps | |
| File Previewfile-preview | files-sdk | Components | Free | 2 deps | |
| File Searchfile-search | files-sdk | Components | Free | 2 deps | |
| Multipart Uploadermultipart-uploader | files-sdk | Components | Free | 2 deps | |
| Share Dialogshare-dialog | files-sdk | Components | Free | 2 deps |
