UNPKG

its-just-ui

Version:

ITS Just UI - The easiest and best React UI component library. Modern, accessible, and customizable components built with TypeScript and Tailwind CSS. Simple to use, production-ready components for building beautiful user interfaces with ease.

215 lines (213 loc) 7.36 kB
import { default as React, ReactNode, HTMLAttributes, ButtonHTMLAttributes, CSSProperties } from 'react'; /** * Upload is a comprehensive file upload component with drag-and-drop support, progress tracking, and compound component architecture. * * ## Features * - **Controlled Component**: Parent manages file state through `files` and `onChange` props * - **Compound Components**: Modular architecture with Dropzone, Preview, Progress, FileList, and Button sub-components * - **Drag & Drop**: Full support for drag-and-drop file uploads with visual feedback * - **File Validation**: Built-in max file size and count restrictions * - **Progress Tracking**: Visual progress indicators for file uploads * - **Multiple Variants**: 5 pre-defined visual styles (default, bordered, dashed, card, ghost) * - **3 Sizes**: Small, medium, and large options * - **Status States**: Built-in support for success, warning, and error states * - **Extensive Styling**: Over 30 style props for complete customization * - **Custom Rendering**: Support for custom file items, dropzone, and progress rendering * - **Accessibility**: Full keyboard navigation and ARIA support * - **Form Ready**: Works seamlessly in forms with required field support * * ## Usage * * ### Basic Usage (Controlled): * ```tsx * const [files, setFiles] = useState<File[]>([]) * * <Upload * files={files} * onChange={setFiles} * accept="image/*" * multiple * /> * ``` * * ### With Restrictions: * ```tsx * <Upload * files={files} * onChange={setFiles} * maxFiles={5} * maxSize={5 * 1024 * 1024} // 5MB * accept=".pdf,.doc,.docx" * helperText="PDF or Word documents only. Max 5 files, 5MB each." * /> * ``` * * ### Using Compound Components: * ```tsx * <Upload files={files} onChange={setFiles}> * <Upload.Dropzone className="custom-dropzone"> * <MyCustomDropzoneContent /> * </Upload.Dropzone> * <Upload.FileList> * <Upload.Button>Select Files</Upload.Button> * </Upload.FileList> * </Upload> * ``` * * ### With Custom File Preview: * ```tsx * <Upload * files={files} * onChange={setFiles} * renderFileItem={(file, index) => ( * <div className="custom-file-item"> * <Upload.Preview file={file} /> * <span>{file.file.name}</span> * <Upload.Progress file={file} /> * </div> * )} * /> * ``` * * ### Form Integration: * ```tsx * <form onSubmit={handleSubmit}> * <Upload * files={files} * onChange={setFiles} * label="Upload Documents" * required * helperText="Please upload supporting documents" * /> * <button type="submit">Submit</button> * </form> * ``` * * @example * ```tsx * // Simple image upload * <Upload * files={files} * onChange={setFiles} * accept="image/*" * variant="dashed" * size="lg" * /> * * // Async upload with progress * <Upload * files={files} * onChange={setFiles} * onUploadStart={(file) => console.log('Starting upload:', file.name)} * onUploadProgress={(file, progress) => console.log(`${file.name}: ${progress}%`)} * onUploadComplete={(file) => console.log('Completed:', file.name)} * /> * ``` */ export interface FileWithProgress { id: string; file: File; progress?: number; status?: 'pending' | 'uploading' | 'success' | 'error'; error?: string; } export type UploadVariant = 'default' | 'bordered' | 'dashed' | 'card' | 'ghost'; export type UploadSize = 'sm' | 'md' | 'lg'; export type UploadStatus = 'default' | 'success' | 'warning' | 'error'; export interface UploadStyleProps { borderWidth?: string | number; borderColor?: string; borderStyle?: string; borderRadius?: string | number; fontSize?: string | number; fontWeight?: string | number; fontFamily?: string; textColor?: string; placeholderColor?: string; backgroundColor?: string; hoverBackgroundColor?: string; activeColor?: string; focusRingColor?: string; focusRingWidth?: string | number; focusRingOffset?: string | number; focusBorderColor?: string; focusBackgroundColor?: string; boxShadow?: string; focusBoxShadow?: string; padding?: string | number; paddingX?: string | number; paddingY?: string | number; margin?: string | number; gap?: string | number; uploadIconColor?: string; deleteIconColor?: string; successIconColor?: string; errorIconColor?: string; transitionDuration?: string | number; } export interface UploadProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'onError' | 'onDrop'>, UploadStyleProps { files?: File[]; onChange?: (files: File[]) => void; accept?: string; multiple?: boolean; maxFiles?: number; maxSize?: number; disabled?: boolean; required?: boolean; loading?: boolean; variant?: UploadVariant; size?: UploadSize; status?: UploadStatus; label?: ReactNode; helperText?: ReactNode; emptyStateMessage?: ReactNode; onDrop?: (files: File[]) => void; onUploadStart?: (file: File) => void; onUploadProgress?: (file: File, progress: number) => void; onUploadComplete?: (file: File) => void; onRemoveFile?: (file: File) => void; onError?: (error: Error, file?: File) => void; renderFileItem?: (file: FileWithProgress, index: number) => ReactNode; renderDropzone?: (isDragging: boolean) => ReactNode; renderProgress?: (file: FileWithProgress) => ReactNode; dropzoneStyle?: CSSProperties; fileListStyle?: CSSProperties; buttonStyle?: CSSProperties; progressStyle?: CSSProperties; previewStyle?: CSSProperties; } interface UploadContextValue { files: FileWithProgress[]; setFiles: (files: FileWithProgress[]) => void; addFiles: (newFiles: File[]) => void; removeFile: (fileId: string) => void; updateFileProgress: (fileId: string, progress: number) => void; updateFileStatus: (fileId: string, status: FileWithProgress['status'], error?: string) => void; props: UploadProps; isDragging: boolean; setIsDragging: (isDragging: boolean) => void; } export declare const useUploadContext: () => UploadContextValue; export interface DropzoneProps extends HTMLAttributes<HTMLDivElement> { children?: ReactNode; } export interface UploadProgressProps extends HTMLAttributes<HTMLDivElement> { file: FileWithProgress; } export interface PreviewProps extends HTMLAttributes<HTMLDivElement> { file: FileWithProgress; } export interface FileListProps extends HTMLAttributes<HTMLDivElement> { children?: ReactNode; } export interface UploadButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { children?: ReactNode; } export declare const Upload: React.ForwardRefExoticComponent<UploadProps & React.RefAttributes<HTMLDivElement>> & { Dropzone: React.ForwardRefExoticComponent<DropzoneProps & React.RefAttributes<HTMLDivElement>>; Preview: React.ForwardRefExoticComponent<PreviewProps & React.RefAttributes<HTMLDivElement>>; Progress: React.ForwardRefExoticComponent<UploadProgressProps & React.RefAttributes<HTMLDivElement>>; FileList: React.ForwardRefExoticComponent<FileListProps & React.RefAttributes<HTMLDivElement>>; Button: React.ForwardRefExoticComponent<UploadButtonProps & React.RefAttributes<HTMLButtonElement>>; }; export {};