Skip to main content

How Dropup Works

Dropup is built around the concept of headless UI - it handles all the complex file upload logic while giving you complete control over the visual presentation.

Architecture

┌─────────────────────────────────────────────────────────────┐
│ Your React Component │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Drop Zone │ │ File List │ │ Upload Button │ │
│ │ (your UI) │ │ (your UI) │ │ (your UI) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ useDropup Hook ││
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌─────────┐ ││
│ │ │Validation │ │ State │ │ Upload │ │ Platform│ ││
│ │ │ Engine │ │ Manager │ │ Engine │ │ Adapter │ ││
│ │ └───────────┘ └───────────┘ └───────────┘ └─────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘

Key Components

1. State Manager

Dropup uses React's useReducer for predictable state management:

  • Tracks all files and their statuses
  • Manages drag state
  • Handles upload progress
  • Provides computed values

2. Validation Engine

Before files are added, they go through validation:

const { files } = useDropup({
accept: 'image/*', // File type validation
maxSize: 5 * 1024 * 1024, // Max file size
minSize: 1024, // Min file size
maxFiles: 10, // Max number of files
maxWidth: 4096, // Max image width
maxHeight: 4096, // Max image height
customRules: [ // Custom validation
(file) => file.name.length < 100 || 'Filename too long'
],
});

3. Upload Engine

The upload engine handles:

  • Simple uploads (single request per file)
  • Chunked uploads (split large files)
  • Retry logic with exponential backoff
  • Concurrent upload management
  • Progress tracking

4. Platform Adapter

Dropup works across platforms:

  • Web - Uses native browser APIs
  • React Native - Uses native file handling
  • SSR - Safe for server-side rendering

Data Flow

User Action → Validation → State Update → Upload → Callbacks
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
Select/ Accept/Reject files[] XHR/Fetch onComplete
Drop files Updated Progress onError

Design Principles

1. Headless First

No built-in UI components - you build exactly what you need:

// You control the entire UI
<div {...getDropProps()}>
<YourCustomDropZone />
<input {...getInputProps()} />
</div>

2. Type Safety

Full TypeScript support with comprehensive types:

import type { DropupFile, UseDropupOptions } from '@samithahansaka/dropup';

const options: UseDropupOptions = {
accept: 'image/*',
onUploadComplete: (file: DropupFile) => {
console.log(file.uploadedUrl);
},
};

3. Tree Shakeable

Import only what you need:

// Core only (~10KB)
import { useDropup } from '@samithahansaka/dropup';

// Add cloud support when needed
import { createS3Uploader } from '@samithahansaka/dropup/cloud/s3';

// Add image processing when needed
import { compressImage } from '@samithahansaka/dropup/image';

4. Progressive Enhancement

Start simple, add features as needed:

// Basic usage
const { files } = useDropup();

// Add validation
const { files } = useDropup({ maxSize: 10_000_000 });

// Add auto-upload
const { files } = useDropup({
maxSize: 10_000_000,
upload: { url: '/api/upload' },
autoUpload: true,
});

// Add cloud storage
const { files } = useDropup({
upload: createS3Uploader({ getPresignedUrl }),
});