export type ImageFormat = 'webp' | 'avif' | 'jpeg' | 'png'; export type RemotePattern = { protocol?: 'http' | 'https'; hostname: string; port?: string; pathname?: string; }; export type ImageLoaderParams = { src: string; width: number; quality: number; }; export type ImageLoader = (params: ImageLoaderParams) => string; export type ImageConfig = { /** Breakpoints for device-width responsive images (default: [640, 750, 828, 1080, 1200, 1920, 2048, 3840]) */ deviceSizes?: number[]; /** Breakpoints for fixed-width images (default: [16, 32, 48, 64, 96, 128, 256, 384]) */ imageSizes?: number[]; /** Output formats in preference order (default: ['webp']). Add 'avif' for smaller files at slower encode. */ formats?: ImageFormat[]; /** Minimum cache TTL in seconds (default: 60) */ minimumCacheTTL?: number; /** Allowed remote image origins */ remotePatterns?: RemotePattern[]; /** Default quality 1-100 (default: 75) */ quality?: number; /** Custom URL builder — overrides the default optimization endpoint */ loader?: ImageLoader; /** Optimization endpoint path (default: '/_absolute/image') */ path?: string; /** Globally disable image optimization — serve images as-is */ unoptimized?: boolean; }; export type ImageProps = { /** Image source URL or path */ src: string; /** Alt text for accessibility (required) */ alt: string; /** Intrinsic width in pixels (required unless fill) */ width?: number; /** Intrinsic height in pixels (required unless fill) */ height?: number; /** Fill parent container with position: absolute */ fill?: boolean; /** Quality 1-100 (default: 75) */ quality?: number; /** Responsive sizes attribute (e.g., "(max-width: 768px) 100vw, 50vw") */ sizes?: string; /** Custom URL builder for this image */ loader?: ImageLoader; /** Bypass optimization for this image */ unoptimized?: boolean; /** Loading strategy (default: "lazy") */ loading?: 'lazy' | 'eager'; /** Add and set loading="eager" + fetchPriority="high" */ priority?: boolean; /** Placeholder while loading: "blur" uses blurDataURL, "empty" shows nothing, or pass a data URI */ placeholder?: 'blur' | 'empty' | string; /** Base64 blur placeholder data URI (auto-generated for build-time images) */ blurDataURL?: string; /** CSS class name */ className?: string; /** Inline styles */ style?: Record; /** Callback when image loads */ onLoad?: (() => void) | ((event: Event) => void); /** Callback on load error */ onError?: (() => void) | ((event: Event) => void); /** CORS setting */ crossOrigin?: 'anonymous' | 'use-credentials' | ''; /** Referrer policy */ referrerPolicy?: '' | 'no-referrer' | 'no-referrer-when-downgrade' | 'origin' | 'origin-when-cross-origin' | 'same-origin' | 'strict-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url'; /** Fetch priority hint */ fetchPriority?: 'high' | 'low' | 'auto'; /** Override the final src attribute on the rendered */ overrideSrc?: string; };