Dropzone
files-sdk/dropzoneFreeComponent
Drag-and-drop (or click) upload area wired to files-sdk/react.
Install it
npx shadcn@latest add https://files-sdk.dev/r/dropzone.jsonSource
1"use client";23import type { UseFilesResult } from "files-sdk/react";4import {5 CheckCircle2Icon,6 Loader2Icon,7 UploadIcon,8 XCircleIcon,9} from "lucide-react";10import {11 createContext,12 useCallback,13 useContext,14 useMemo,15 useRef,16 useState,17} from "react";18import type { ReactNode } from "react";1920import { Button } from "@/components/ui/button";21import { cn } from "@/lib/utils";2223export interface UploadedEntry {24 key: string;25 /** Display name — the relative path for folder uploads, else the file name. */26 name: string;27}2829interface PendingFile {30 file: File;31 /** Path relative to the picked/dropped root (e.g. `docs/guide.md`). Empty for plain files. */32 path: string;33}3435interface DropzoneContextValue {36 accept?: string;37 directory: boolean;38 maxFiles: number;39 maxSize?: number;40 isUploading: boolean;41 uploaded: UploadedEntry[];42 /** Failure summary for the most recent batch, if any. */43 error?: string;44 open: () => void;45}4647const formatBytes = (bytes: number): string => {48 if (bytes === 0) {49 return "0 B";50 }51 const units = ["B", "KB", "MB", "GB", "TB"];52 const exponent = Math.min(53 Math.floor(Math.log(bytes) / Math.log(1024)),54 units.length - 155 );56 return `${(bytes / 1024 ** exponent).toFixed(exponent === 0 ? 0 : 1)} ${units[exponent]}`;57};5859const DropzoneContext = createContext<DropzoneContextValue | null>(null);6061const useDropzoneContext = (): DropzoneContextValue => {62 const ctx = useContext(DropzoneContext);63 if (!ctx) {64 throw new Error("Dropzone components must be used inside <Dropzone>.");65 }66 return ctx;67};6869/** Drain a directory reader — `readEntries` returns results in batches of ≤100. */70const readAllEntries = (71 reader: FileSystemDirectoryReader72): Promise<FileSystemEntry[]> =>73 // oxlint-disable-next-line promise/avoid-new -- readEntries is callback-only; there is no promise API to reuse74 new Promise((resolve, reject) => {75 const entries: FileSystemEntry[] = [];76 const drain = (): void => {77 reader.readEntries((batch) => {78 if (batch.length === 0) {79 resolve(entries);80 return;81 }82 entries.push(...batch);83 drain();84 }, reject);85 };86 drain();87 });8889const entryFile = (entry: FileSystemFileEntry): Promise<File> =>90 // oxlint-disable-next-line promise/avoid-new -- FileSystemFileEntry.file is callback-only; there is no promise API to reuse91 new Promise((resolve, reject) => {92 entry.file(resolve, reject);93 });9495// … 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 | |
| File Actionsfile-actions | files-sdk | Components | Free | 2 deps | |
| File Browserfile-browser | files-sdk | Components | Free | 2 deps | |
| File Listfile-list | 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 |
