UNPKG

react-img-toolkit

Version:

A lightweight React library for optimizing image loading through preloading, lazy loading, and caching capabilities

590 lines (457 loc) 16.5 kB
# React Image Toolkit A lightweight React library for optimizing image loading through preloading, lazy loading, and caching capabilities. ## Features - 🚀 **Image Preloading**: Load images in advance for instant display, especially useful when working with Electron.js since preloaded images will continue displaying even if the internet connection is lost. - 🎯 **Lazy Loading**: Load images only when they enter the viewport - 💾 **Image Caching**: Cache images for faster subsequent loads - 📊 **Status Tracking**: Monitor image loading states - 🎨 **TypeScript Support**: Full TypeScript support with type definitions - 🪶 **Lightweight**: No external dependencies except React - 🖼️ **Custom Configurations**: Supports cross-origin, referrer policies, and direct access to the HTMLImageElement for advanced use cases. ## Installation ```bash npm install react-img-toolkit ``` ## Usage ### Image Preloader Component ### data can be any structured, ImagePreloader will extract image URLs from it. ```tsx import { ImagePreloader } from 'react-img-toolkit'; function Gallery() { const data = { images: [ 'https://example.com/image1.jpg', 'https://example.com/image2.jpg', ], otherData: 'Hello World!', }; return ( <ImagePreloader data={data} onSuccess={() => console.log('All images loaded!')} onError={(error) => console.error('Failed to load:', error)} > {/* Your gallery content */} </ImagePreloader> ); } ``` ### Hooks #### useImagePreloader Preload multiple images and track their loading status. The `onSuccess` callback is executed only when there are uncached image URLs that need to be loaded. If all images are cached, the `onSuccess` callback does not run. This hook checks for browser caching before executing the `onSuccess` callback, ensuring it only runs when necessary. For example, if all images are cached, the `onSuccess` callback will not be executed, but if there are uncached images, the `onSuccess` callback will run after those images are loaded. ```tsx import { useImagePreloader } from 'react-img-toolkit'; function Gallery() { const { imageUrls } = useImagePreloader({ data: [ 'https://example.com/image1.jpg', 'https://example.com/image2.jpg' ], onSuccess: () => console.log("All uncached images preloaded successfully"), onError: (error) => console.error("Failed to preload images:", error), }); return ( <div> <p>Loaded {imageUrls.length} images</p> {imageUrls.map((url, index) => ( <img key={index} src={url} alt={`Image ${index + 1}`} /> ))} </div> ); } ``` #### useLazyImage Load images only when they enter the viewport: ```tsx import { useLazyImage } from 'react-img-toolkit'; function LazyImage() { const { ref, isIntersecting, isLoaded } = useLazyImage({ src: 'https://example.com/large-image.jpg', options: { threshold: 0.5, rootMargin: '200px', } }); return ( <div ref={ref}> {isLoaded && ( <img src="https://example.com/large-image.jpg" alt="Lazy loaded" /> )} </div> ); } ``` #### useImageCache Cache images for faster subsequent loads: ```tsx import { useImageCache } from 'react-img-toolkit'; function CachedImage() { const { cachedSrc, loading, isCached } = useImageCache({ src: 'https://example.com/image.jpg', }); if (loading) return <div>Loading...</div>; return <img src={cachedSrc} alt="Cached image" />; } ``` #### useImageLoad The `useImageLoad` hook is particularly useful when you need direct access to the DOM image element, such as when working with canvas or WebGL. It provides: - Full control over image loading configuration - Cross-origin resource sharing (CORS) settings - Referrer policy configuration - Direct access to the HTMLImageElement - Loading state and error handling Load images with custom configurations, particularly useful for canvas applications: ```tsx import { useImageLoad } from 'react-img-toolkit'; function CanvasImage() { const { image, isLoading, error } = useImageLoad({ url: 'https://example.com/image.jpg', crossOrigin: 'anonymous', referrerPolicy: 'no-referrer' }); if (isLoading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> <canvas ref={canvasRef => { if (canvasRef && image) { const ctx = canvasRef.getContext('2d'); if (ctx) { canvasRef.width = image.width; canvasRef.height = image.height; ctx.drawImage(image, 0, 0); } } }} /> </div> ); } ``` #### useImageStatus Track the loading status of an image: ```tsx import { useImageStatus } from 'react-img-toolkit'; function ImageWithStatus() { const status = useImageStatus({ src: 'https://example.com/image.jpg' }); return ( <div> <p>Status: {status}</p> {status === 'loaded' && <img src="https://example.com/image.jpg" alt="Loaded" />} </div> ); } ``` #### useImageOptimizer The `useImageOptimizer` hook is designed to optimize images by resizing, adjusting quality, and applying transformations such as rotation and flipping. It manages loading states and errors during the optimization process. ### Key Features 1. **Image Resizing**: - Allows you to specify maximum width and height, ensuring that images do not exceed these dimensions. 2. **Quality Control**: - Supports adjustable quality settings for JPEG and WebP formats (from 0 to 1). 3. **Format Handling**: - Detects the MIME type of the image if not specified, supporting formats like JPEG, PNG, WebP, and GIF. 4. **Transformations**: - Provides options to rotate the image and flip it horizontally or vertically. 5. **Transparency Management**: - Option to keep transparency for PNG and WebP formats, or remove it for JPEG and WebP if specified. 6. **Asynchronous Processing**: - Utilizes a `FileReader` to load images and a `canvas` element for the optimization process, ensuring efficient handling of image data. 7. **Error Management**: - Provides error handling to capture and report issues during the optimization process. ### Usage Example Here’s a simple example of how to use `useImageOptimizer`: ```tsx import { useImageOptimizer } from 'react-img-toolkit'; function ImageOptimizerComponent() { const { optimizeImage, loading, error } = useImageOptimizer(); const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => { const file = event.target.files?.[0]; if (file) { const options = { maxWidth: 800, maxHeight: 600, quality: 0.8, rotate: 90 }; const optimizedBlob = await optimizeImage(file, options); // Handle the optimized image blob (e.g., display it, upload it, etc.) } }; return ( <div> <input type="file" onChange={handleFileChange} /> {loading && <p>Loading...</p>} {error && <p>Error: {error}</p>} </div> ); } ``` ## useImageConverter The `useImageConverter` hook provides a way to convert images between different formats while managing loading states and errors. It supports various options for customization during the conversion process. ### Key Features 1. **Format Support**: - Converts images to the following formats: JPEG, PNG, WebP, and GIF. 2. **Quality Control**: - Allows for adjustable quality settings for JPEG and WebP formats (from 0 to 1). 3. **Transparency Handling**: - Option to keep transparency for PNG and WebP formats. - Removes transparency for JPEG and WebP if specified. 4. **Asynchronous Processing**: - Utilizes a `FileReader` to load images and a `canvas` element for the conversion process, ensuring efficient handling of image data. 5. **Error Management**: - Provides error handling to capture and report issues during the conversion process. ### Usage Example Here’s a simple example of how to use `useImageConverter`: ```tsx import { useImageConverter } from 'react-img-toolkit'; function ImageConverterComponent() { const { convertImage, loading, error } = useImageConverter(); const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => { const file = event.target.files?.[0]; if (file) { const options = { format: 'image/webp', quality: 0.8, keepTransparency: true }; const convertedBlob = await convertImage(file, options); // Handle the converted image blob (e.g., display it, upload it, etc.) } }; return ( <div> <input type="file" onChange={handleFileChange} /> {loading && <p>Loading...</p>} {error && <p>Error: {error}</p>} </div> ); } ``` ### useImageOptimizer The `useImageOptimizer` hook is designed to optimize images by resizing, adjusting quality, and applying transformations such as rotation and flipping. It manages loading states and errors during the optimization process. ### Key Features 1. **Image Resizing**: - Allows you to specify maximum width and height, ensuring that images do not exceed these dimensions. 2. **Quality Control**: - Supports adjustable quality settings for JPEG and WebP formats (from 0 to 1). 3. **Format Handling**: - Detects the MIME type of the image if not specified, supporting formats like JPEG, PNG, WebP, and GIF. 4. **Transformations**: - Provides options to rotate the image and flip it horizontally or vertically. 5. **Transparency Management**: - Option to keep transparency for PNG and WebP formats, or remove it for JPEG and WebP if specified. 6. **Asynchronous Processing**: - Utilizes a `FileReader` to load images and a `canvas` element for the optimization process, ensuring efficient handling of image data. 7. **Error Management**: - Provides error handling to capture and report issues during the optimization process. ### Usage Example Here’s a simple example of how to use `useImageOptimizer`: ```tsx import { useImageOptimizer } from 'react-img-toolkit'; function ImageOptimizerComponent() { const { optimizeImage, loading, error } = useImageOptimizer(); const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => { const file = event.target.files?.[0]; if (file) { const options = { maxWidth: 800, maxHeight: 600, quality: 0.8, rotate: 90 }; const optimizedBlob = await optimizeImage(file, options); // Handle the optimized image blob (e.g., display it, upload it, etc.) } }; return ( <div> <input type="file" onChange={handleFileChange} /> {loading && <p>Loading...</p>} {error && <p>Error: {error}</p>} </div> ); } ``` ## useImageMeta The `useImageMeta` hook extracts metadata from an image file, providing information such as dimensions, type, size, and name. **Key Features**: 1. **Metadata Extraction**: Retrieves width, height, type, size, and name of the image. 2. **Error Handling**: Captures errors during file reading and image loading. 3. **State Management**: Uses React's state to manage metadata and error states. **Usage Example**: ```tsx import { useImageMeta } from 'react-img-toolkit'; function ImageUploader() { const [file, setFile] = useState<File | null>(null); const { metadata, error } = useImageMeta(file); const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => { const selectedFile = event.target.files?.[0]; if (selectedFile) { setFile(selectedFile); } }; return ( <div> <input type="file" onChange={handleFileChange} /> {error && <p>Error: {error}</p>} {metadata && ( <div> <p>Name: {metadata.name}</p> <p>Type: {metadata.type}</p> <p>Size: {metadata.size} bytes</p> <p>Dimensions: {metadata.width} x {metadata.height}</p> </div> )} </div> ); } ``` ## API Reference ### ImagePreloader Component | Prop | Type | Description | |-----------|------------------------|-------------------------------------| | data | any | Any structured data. | | onSuccess | () => void | Callback when all images are loaded | | onError | (error: Error) => void | Callback when an error occurs | | children | ReactNode | Content to render | ### useImagePreloader Hook ```typescript interface ImagePreloaderProps { data?: any; // Any data to extract URLs from onSuccess?: () => void; // Callback on successful preload onError?: (error: Error) => void; // Callback on preload error children: React.ReactNode; // Child components to render } interface ImagePreloaderState { imageUrls: string[]; count: number; } function useImagePreloader({ data = {}, onSuccess, onError, }: UseImagePreloaderProps = {}): ImagePreloaderState; ``` ### useLazyImage Hook ```typescript interface UseLazyImageProps { src: string; options?: { threshold?: number; rootMargin?: string; }; } interface UseLazyImageResult { ref: RefObject<HTMLElement>; isIntersecting: boolean; isLoaded: boolean; } function useLazyImage({ src, options, }: UseLazyImageProps): UseLazyImageResult; ``` ### useImageCache Hook ```typescript interface UseImageCacheProps { src: string; } interface UseImageCacheResult { cachedSrc: string | null; loading: boolean; isCached: boolean; } function useImageCache({ src }: UseImageCacheProps): UseImageCacheResult; ``` ### useImageLoad Hook ```typescript interface UseImageLoadProps { url: string; crossOrigin?: HTMLImageElement['crossOrigin']; referrerPolicy?: HTMLImageElement['referrerPolicy']; } interface UseImageLoadResult { image: HTMLImageElement | null; isLoading: boolean; error: Error | null; } function useImageLoad( { url, crossOrigin, referrerPolicy }: UseImageLoadProps ): UseImageLoadResult; ``` ### useImageStatus Hook ```typescript interface UseImageStatusProps { src: string; } interface UseImageStatusResult { status: 'idle' | 'loading' | 'loaded' | 'error'; } function useImageStatus( { src }: UseImageStatusProps ): UseImageStatusResult; ``` ### useImageConverter Hook ```typescript interface UseImageConverterProps { src: string; format: string; } interface UseImageConverterResult { convert: string | null; status: 'idle' | 'loading' | 'loaded' | 'error'; } function useImageConverter( { src, format }: UseImageConverterProps ): UseImageConverterResult; ``` ### useImageOptimizer Hook ```typescript interface UseImageOptimizerProps { maxWidth?: number; maxHeight?: number; quality?: number; rotate?: number; flipHorizontally?: boolean; flipVertically?: boolean; } interface UseImageOptimizerResult { optimizeImage: (file: File, options: UseImageOptimizerProps) => Promise<Blob | null>; loading: boolean; error: Error | null; } function useImageOptimizer(): UseImageOptimizerResult; ``` ### useImageMeta Hook ```typescript interface UseImageMetaProps { file: File | null; // The image file to extract metadata from } interface UseImageMetaResult { metadata: { width: number; height: number; type: string; size: number; name: string; } | null; // Image metadata or null if not available error: string | null; // Error message if any error occurs } function useImageMeta(file: UseImageMetaProps): UseImageMetaResult; ``` ## Development 1. Clone the repository: ```bash git clone https://github.com/IxtiyorDeveloper/react-img-toolkit.git cd react-img-toolkit ``` 2. Install dependencies: ```bash npm install ``` 3. Start development server: ```bash npm run dev ``` 4. Run tests: ```bash npm test ``` ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## License MIT