@astrify/react-s3-upload
Version:
React file upload system built for S3-compatible storage with shadcn/ui components
207 lines (197 loc) • 6.53 kB
TypeScript
import * as react_jsx_runtime from 'react/jsx-runtime';
import * as React from 'react';
import { ReactNode } from 'react';
import { FileRejection, Accept } from 'react-dropzone';
interface DropzoneProps {
onDrop?: (acceptedFiles: File[], rejectedFiles: FileRejection[]) => void;
maxSize?: number;
maxFiles?: number;
accept?: Accept;
className?: string;
children?: React.ReactNode;
hideDefaultContent?: boolean;
emptyIcon?: React.ReactNode;
emptyTitle?: string;
emptyDescription?: string;
}
declare function Dropzone({ onDrop: onDropProp, maxSize: maxSizeProp, maxFiles: maxFilesProp, accept: acceptProp, className, emptyIcon, emptyTitle, emptyDescription, }: DropzoneProps): react_jsx_runtime.JSX.Element;
declare function Errors(): react_jsx_runtime.JSX.Element;
interface HeaderProps {
className?: string;
title?: string;
showAddButton?: boolean;
showClearButton?: boolean;
addButtonText?: string;
clearButtonText?: string;
}
declare function Header({ className, title, showAddButton, showClearButton, addButtonText, clearButtonText, }: HeaderProps): react_jsx_runtime.JSX.Element | null;
interface ListProps {
showActions?: boolean;
showImagePreviews?: boolean;
className?: string;
}
declare function List({ showActions, showImagePreviews, className, }: ListProps): react_jsx_runtime.JSX.Element | null;
interface FileUpload {
id: string;
name: string;
size: number;
type: string;
sha256: string;
url: string;
status: UploadStatus;
progress: number;
error?: string;
preview?: string;
duplicateAlert?: boolean;
file?: File;
}
/**
* Payload for Signed URL endpoint
*/
interface SignedUrlRequest {
name: string;
size: number;
type: string;
sha256: string;
preview?: string;
}
/**
* Response from signed URL endpoint
*/
interface SignedUrlResponse {
sha256: string;
bucket: string;
key: string;
url: string;
extension?: string;
filename?: string;
}
/**
* File upload status
*/
type UploadStatus = "pending" | "uploading" | "complete" | "error";
/**
* Error types for upload failures
*/
type UploadErrorType = "no_files" | "server_error" | "network_error" | "s3_upload" | "invalid_response" | "validation_error" | "duplicate_file" | "unknown";
/**
* Upload error structure
*/
interface UploadError {
type: UploadErrorType;
message: string;
details?: unknown;
}
type FileType = File | {
name: string;
size: number;
type: string;
};
/**
* Upload library interface for dependency injection
*/
interface UploadLib {
calculateSHA256: (file: File) => Promise<string>;
requestBatchSignedUrls: (files: Array<{
file: File;
sha256: string;
}>, signedUrlEndpoint?: string, signedUrlHeaders?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>)) => Promise<SignedUrlResponse[]>;
uploadFile: (params: {
file: File;
signedUrl: SignedUrlResponse;
sha256: string;
onProgress?: (sha256: string, progress: number) => void;
signal?: AbortSignal;
}) => Promise<void>;
}
/**
* Configuration options for the FileUploadProvider
*/
interface FileUploadConfig {
maxFiles?: number;
maxSize?: number;
accept?: Accept;
signedUrlEndpoint?: string;
signedUrlHeaders?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
onUploadComplete?: (files: FileUpload[]) => void;
onUploadError?: (errors: Array<{
file: File;
error: unknown;
}>) => void;
onFilesChange?: (files: File[]) => void;
uploadLib?: UploadLib;
}
/**
* Return type for the useFileUpload hook
*/
interface UseFileUploadResult {
files: FileUpload[];
errors: UploadError[];
isUploading: boolean;
remainingSlots: number;
config: FileUploadConfig;
hasPending: boolean;
hasUploading: boolean;
hasErrors: boolean;
hasComplete: boolean;
addFiles: (files: File[]) => Promise<void>;
removeFile: (fileId: string) => void;
removeAll: () => void;
retryUpload: (fileId: string) => Promise<void>;
reset: () => void;
addErrors: (errors: UploadError[]) => void;
clearErrors: () => void;
canAcceptMore: boolean;
acceptedFileTypes: Accept | undefined;
maxFileSize: number;
}
interface FileUploadProviderProps {
children: ReactNode;
config?: FileUploadConfig;
defaultFiles?: FileUpload[];
}
declare function FileUploadProvider({ children, config, defaultFiles, }: FileUploadProviderProps): react_jsx_runtime.JSX.Element;
declare function useFileUpload(): UseFileUploadResult;
declare function useFileErrors(): UploadError[];
/**
* Uploads a single file to S3-compatible storage
* Returns void on success, throws error on failure
*/
declare function uploadFile({ file, signedUrl, sha256, onProgress, signal, }: {
file: File;
signedUrl: SignedUrlResponse;
sha256: string;
onProgress?: (sha256: string, progress: number) => void;
signal?: AbortSignal;
}): Promise<void>;
/**
* Calculate SHA-256 hash of a file
*/
declare function calculateSHA256(file: File): Promise<string>;
/**
* Request signed URLs for multiple files in a single request
*/
declare function requestBatchSignedUrls(files: Array<{
file: File;
sha256: string;
}>, signedUrlEndpoint?: string, signedUrlHeaders?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>)): Promise<SignedUrlResponse[]>;
/**
* Upload a file to S3-compatible storage using a presigned URL
* Supports any S3-compatible service: AWS S3, DigitalOcean Spaces,
* Cloudflare R2, MinIO, Wasabi, Backblaze B2, etc.
*/
declare function uploadToS3Storage(params: {
file: File;
signedUrl: string;
headers?: Record<string, string>;
onProgress?: (progress: number) => void;
signal?: AbortSignal;
}): Promise<void>;
/**
* Format bytes as human-readable text
*/
declare function formatBytes(bytes: number, options?: {
si?: boolean;
decimalPlaces?: number;
}): string;
export { Dropzone, Errors, type FileType, type FileUpload, type FileUploadConfig, FileUploadProvider, type FileUploadProviderProps, Header, List, type SignedUrlRequest, type SignedUrlResponse, type UploadError, type UploadErrorType, type UploadLib, type UploadStatus, type UseFileUploadResult, calculateSHA256, formatBytes, requestBatchSignedUrls, uploadFile, uploadToS3Storage, useFileErrors, useFileUpload };