1.0.9 • Published 4 months ago

react-img-toolkit v1.0.9

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

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

npm install react-img-toolkit

Usage

Image Preloader Component

data can be any structured, ImagePreloader will extract image URLs from it.

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.

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:

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:

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:

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:

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:

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:

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:

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:

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

PropTypeDescription
dataanyAny structured data.
onSuccess() => voidCallback when all images are loaded
onError(error: Error) => voidCallback when an error occurs
childrenReactNodeContent to render

useImagePreloader Hook

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

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

interface UseImageCacheProps {
  src: string;
}

interface UseImageCacheResult {
  cachedSrc: string | null;
  loading: boolean;
  isCached: boolean;
}
function useImageCache({ src }: UseImageCacheProps): UseImageCacheResult;

useImageLoad Hook

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

interface UseImageStatusProps {
  src: string;
}

interface UseImageStatusResult {
  status: 'idle' | 'loading' | 'loaded' | 'error';
}

function useImageStatus(
  { src }: UseImageStatusProps
): UseImageStatusResult;

useImageConverter Hook

interface UseImageConverterProps {
  src: string;
  format: string;
}

interface UseImageConverterResult {
  convert: string | null;
  status: 'idle' | 'loading' | 'loaded' | 'error';
}

function useImageConverter(
  { src, format }: UseImageConverterProps
): UseImageConverterResult;

useImageOptimizer Hook

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

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:
    git clone https://github.com/IxtiyorDeveloper/react-img-toolkit.git
    cd react-img-toolkit
  2. Install dependencies:
    npm install
  3. Start development server:
    npm run dev
  4. Run tests:
    npm test

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT