"use client"; /** * Next.js image components and hooks for the asset caching module */ import { useEffect, useState } from "react"; import { AssetLoader, CacheOptions } from "@shopkit/asset-cache"; /** * Hook to use a cached image * @param src Image source URL * @param options Caching options * @returns Image URL and loading state */ export function useAssetCacheImage( src: string, options?: CacheOptions ): { imageUrl: string | null; isLoading: boolean; error: Error | null; } { const [imageUrl, setImageUrl] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let isMounted = true; const loadImage = async () => { try { setIsLoading(true); // Check if the image is cached const isCached = await AssetLoader.isCached(src); if (isCached) { // Load from cache const result = await AssetLoader.load(src, options); if (result.success && isMounted && result.data) { const url = URL.createObjectURL(result.data); setImageUrl(url); setError(null); } } else { // Not cached, use original URL and cache for next time setImageUrl(src); AssetLoader.preload(src, options).catch(() => { // Ignore caching errors }); } } catch (err) { if (isMounted) { setError(err instanceof Error ? err : new Error(String(err))); setImageUrl(src); // Fallback to original URL } } finally { if (isMounted) { setIsLoading(false); } } }; loadImage(); return () => { isMounted = false; // Revoke object URL if it exists if (imageUrl && imageUrl !== src) { URL.revokeObjectURL(imageUrl); } }; }, [src, options]); return { imageUrl, isLoading, error }; }