@winglet/react-utils
Version:
React utility library providing custom hooks, higher-order components (HOCs), and utility functions to enhance React application development with improved reusability and functionality
97 lines (96 loc) • 3.84 kB
TypeScript
import { type ComponentType } from 'react';
import type { Fn } from '../../@aileron/declare';
interface BaseProps {
onClick?: Fn<[e?: MouseEvent]>;
}
interface UploaderProps {
acceptFormat?: string[];
onChange?: Fn<[file: File]>;
}
/**
* Transforms any clickable component into a file upload trigger with comprehensive file handling.
*
* This Higher-Order Component (HOC) enhances existing components by adding sophisticated file
* upload capabilities. When the wrapped component is clicked, it opens a native file selection
* dialog and provides callbacks for handling the selected files. The HOC maintains all original
* component functionality while seamlessly integrating file upload behavior.
*
* ### Use Cases
* - **Custom Upload Buttons**: Transform buttons, divs, or any clickable element into file uploaders
* - **Drag-and-Drop Alternative**: Provide click-to-upload fallback for drag-and-drop interfaces
* - **Form Integration**: Add file upload to form controls with custom styling
* - **Image/Document Pickers**: Create specialized file selectors for different content types
*
* ### Key Features
* - Preserves all original component props and behavior
* - Supports file type filtering through accept formats
* - Automatically clears input after file selection to allow repeated uploads
* - Maintains component onClick functionality while adding upload trigger
* - Uses hidden file input for clean UI integration
* - Memory-optimized with React.memo for performance
*
* ### File Handling Details
* - Only handles single file selection (uses first file from FileList)
* - Clears input value after each selection to enable re-selecting the same file
* - Calls original onClick handler before triggering file dialog
* - Provides selected File object directly to onChange callback
*
* @example
* ```typescript
* // Basic button upload
* const UploadButton = withUploader(Button);
* const handleFileUpload = (file: File) => {
* console.log('Selected file:', file.name, file.size);
* // Process file...
* };
*
* <UploadButton onChange={handleFileUpload}>
* Choose File
* </UploadButton>
*
* // Image upload with format restriction
* const ImageUploader = withUploader(({ children, ...props }) => (
* <div className="upload-zone" {...props}>
* {children}
* </div>
* ));
*
* <ImageUploader
* acceptFormat={['.jpg', '.jpeg', '.png', '.gif']}
* onChange={(file) => setSelectedImage(file)}
* >
* <img src={placeholderIcon} alt="Upload" />
* <span>Click to upload image</span>
* </ImageUploader>
*
* // Document upload with multiple formats
* const DocumentPicker = withUploader(Card);
* <DocumentPicker
* acceptFormat={['.pdf', '.doc', '.docx', '.txt']}
* onChange={handleDocumentUpload}
* onClick={(e) => {
* console.log('Upload initiated');
* // Original click handler still works
* }}
* >
* <Icon name="document" />
* <Text>Upload Document</Text>
* </DocumentPicker>
*
* // Integration with existing form controls
* const FileInputField = withUploader(FormField);
* <FileInputField
* label="Profile Picture"
* acceptFormat={['.jpg', '.png']}
* onChange={(file) => {
* setFormData(prev => ({ ...prev, avatar: file }));
* }}
* />
* ```
*
* @typeParam Props - The type definition for the base component's props, must extend BaseProps with onClick
* @param Component - The React component to enhance with file upload functionality
* @returns A memoized component that combines the original component with file upload capabilities
*/
export declare const withUploader: <Props extends BaseProps>(Component: ComponentType<Props>) => import("react").MemoExoticComponent<({ onClick, onChange, acceptFormat, ...props }: Props & UploaderProps) => import("react/jsx-runtime").JSX.Element>;
export {};