react-image-gallery
Version:
React carousel image gallery component with thumbnail and mobile support
412 lines (411 loc) • 15.8 kB
TypeScript
import { CSSProperties, KeyboardEvent, MouseEvent, ReactNode, SyntheticEvent, TouchEvent } from "react";
import type React from "react";
/**
* Image set for responsive images
*/
export interface ImageSet {
srcSet: string;
media: string;
}
/**
* Individual gallery item configuration
*/
export interface GalleryItem {
/** URL of the main image */
original: string;
/** URL of the thumbnail image */
thumbnail?: string;
/** URL of the fullscreen image (defaults to original) */
fullscreen?: string;
/** Original image width for aspect ratio (as string for img attribute) */
originalWidth?: string;
/** Original image height for aspect ratio (as string for img attribute) */
originalHeight?: string;
/** Thumbnail image width */
thumbnailWidth?: string | number;
/** Thumbnail image height */
thumbnailHeight?: string | number;
/** Alt text for the main image */
originalAlt?: string;
/** Alt text for the thumbnail */
thumbnailAlt?: string;
/** Title attribute for the main image */
originalTitle?: string;
/** Title attribute for the thumbnail */
thumbnailTitle?: string;
/** Description text shown below the image */
description?: string;
/** Label shown on the thumbnail */
thumbnailLabel?: string;
/** Additional CSS class for the slide */
originalClass?: string;
/** Additional CSS class for the thumbnail */
thumbnailClass?: string;
/** Additional CSS class for the bullet */
bulletClass?: string;
/** Loading strategy for the main image */
loading?: "eager" | "lazy";
/** Loading strategy for the thumbnail */
thumbnailLoading?: "eager" | "lazy";
/** srcSet for responsive main images */
srcSet?: string;
/** sizes attribute for responsive images */
sizes?: string;
/** Array of image sets for picture element */
imageSet?: ImageSet[];
/** Custom render function for this item */
renderItem?: (item: GalleryItem) => ReactNode;
/** Custom render function for this thumbnail */
renderThumbInner?: (item: GalleryItem) => ReactNode;
/** Click handler for bullet */
bulletOnClick?: (event: MouseEvent<HTMLButtonElement>, index: number) => void;
}
export type ThumbnailPosition = "top" | "bottom" | "left" | "right";
export type SlideEvent = MouseEvent | KeyboardEvent | TouchEvent | Event | SyntheticEvent | undefined;
export type OnSlideCallback = (currentIndex: number) => void;
export type OnBeforeSlideCallback = (nextIndex: number) => void;
export type OnScreenChangeCallback = (fullscreen: boolean) => void;
export type OnPauseCallback = (currentIndex: number) => void;
export type OnPlayCallback = (currentIndex: number) => void;
export type OnClickCallback = (event: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>) => void;
export type OnImageLoadCallback = (event: SyntheticEvent<HTMLImageElement>) => void;
export type OnImageErrorCallback = (event: SyntheticEvent<HTMLImageElement>) => void;
export type OnTouchCallback = (event: TouchEvent<HTMLDivElement>) => void;
export type OnMouseCallback = (event: MouseEvent<HTMLDivElement>) => void;
export type OnBulletClickCallback = (event: MouseEvent<HTMLButtonElement>, index: number) => void;
export type OnThumbnailClickCallback = (event: MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLButtonElement>, index: number) => void;
export type OnThumbnailErrorCallback = (event: SyntheticEvent<HTMLImageElement>) => void;
export type RenderNavCallback = (onClick: (event?: SlideEvent) => void, disabled: boolean) => ReactNode;
export type RenderPlayPauseCallback = (onClick: () => void, isPlaying: boolean) => ReactNode;
export type RenderFullscreenCallback = (onClick: () => void, isFullscreen: boolean) => ReactNode;
export type RenderItemCallback = (item: GalleryItem) => ReactNode;
export type RenderThumbInnerCallback = (item: GalleryItem) => ReactNode;
export type RenderCustomControlsCallback = () => ReactNode;
export interface ImageGalleryProps {
/** Array of gallery items to display */
items: GalleryItem[];
/** Additional CSS class for the gallery container */
additionalClass?: string;
/** Auto-play slideshow on mount */
autoPlay?: boolean;
/** Disable keyboard navigation */
disableKeyDown?: boolean;
/** Disable swipe gestures on main slides */
disableSwipe?: boolean;
/** Disable thumbnail auto-scroll to active thumbnail */
disableThumbnailScroll?: boolean;
/** Disable swipe gestures on thumbnails */
disableThumbnailSwipe?: boolean;
/** Velocity threshold for flick detection (0-1) */
flickThreshold?: number;
/** Separator between current and total in index indicator */
indexSeparator?: string;
/** Enable infinite loop sliding */
infinite?: boolean;
/** Enable right-to-left layout */
isRTL?: boolean;
/** Enable lazy loading of images */
lazyLoad?: boolean;
/** Fallback image URL on error */
onErrorImageURL?: string;
/** Show bullet navigation */
showBullets?: boolean;
/** Maximum number of bullets to show (minimum 3) */
maxBullets?: number;
/** Show fullscreen toggle button */
showFullscreenButton?: boolean;
/** Show current/total index indicator */
showIndex?: boolean;
/** Show left/right navigation arrows */
showNav?: boolean;
/** Show play/pause button */
showPlayButton?: boolean;
/** Show thumbnail strip */
showThumbnails?: boolean;
/** Slide animation duration in milliseconds */
slideDuration?: number;
/** Auto-play interval in milliseconds */
slideInterval?: number;
/** Slide to image on thumbnail hover */
slideOnThumbnailOver?: boolean;
/** Enable vertical sliding instead of horizontal */
slideVertically?: boolean;
/** Initial slide index */
startIndex?: number;
/** Stop event propagation on swipe */
stopPropagation?: boolean;
/** Minimum swipe distance to trigger slide change */
swipeThreshold?: number;
/** Transition duration during swiping */
swipingTransitionDuration?: number;
/** Position of thumbnail strip */
thumbnailPosition?: ThumbnailPosition;
/** Use browser fullscreen API vs modal fullscreen */
useBrowserFullscreen?: boolean;
/** Use translate3d for GPU acceleration */
useTranslate3D?: boolean;
/** Attach keyboard listener to window vs gallery element */
useWindowKeyDown?: boolean;
/** Called before slide transition starts */
onBeforeSlide?: OnBeforeSlideCallback;
/** Called when a bullet is clicked */
onBulletClick?: OnBulletClickCallback;
/** Called when the gallery is clicked */
onClick?: OnClickCallback;
/** Called on main image error */
onImageError?: OnImageErrorCallback;
/** Called when main image loads */
onImageLoad?: OnImageLoadCallback;
/** Called on mouse leave from gallery */
onMouseLeave?: OnMouseCallback;
/** Called on mouse over gallery */
onMouseOver?: OnMouseCallback;
/** Called when auto-play pauses */
onPause?: OnPauseCallback;
/** Called when auto-play starts */
onPlay?: OnPlayCallback;
/** Called when fullscreen state changes */
onScreenChange?: OnScreenChangeCallback;
/** Called after slide transition completes */
onSlide?: OnSlideCallback;
/** Called when a thumbnail is clicked */
onThumbnailClick?: OnThumbnailClickCallback;
/** Called on thumbnail image error */
onThumbnailError?: OnThumbnailErrorCallback;
/** Called on touch end */
onTouchEnd?: OnTouchCallback;
/** Called on touch move */
onTouchMove?: OnTouchCallback;
/** Called on touch start */
onTouchStart?: OnTouchCallback;
/** Custom renderer for bottom navigation (vertical mode) */
renderBottomNav?: RenderNavCallback;
/** Custom renderer for additional controls */
renderCustomControls?: RenderCustomControlsCallback;
/** Custom renderer for fullscreen button */
renderFullscreenButton?: RenderFullscreenCallback;
/** Custom renderer for slide items */
renderItem?: RenderItemCallback;
/** Custom renderer for left navigation */
renderLeftNav?: RenderNavCallback;
/** Custom renderer for play/pause button */
renderPlayPauseButton?: RenderPlayPauseCallback;
/** Custom renderer for right navigation */
renderRightNav?: RenderNavCallback;
/** Custom renderer for thumbnail inner content */
renderThumbInner?: RenderThumbInnerCallback;
/** Custom renderer for top navigation (vertical mode) */
renderTopNav?: RenderNavCallback;
}
export interface ImageGalleryRef {
/** Start auto-play */
play: () => void;
/** Stop auto-play */
pause: () => void;
/** Toggle auto-play */
togglePlay: () => void;
/** Enter fullscreen mode */
fullScreen: () => void;
/** Exit fullscreen mode */
exitFullScreen: () => void;
/** Toggle fullscreen mode */
toggleFullScreen: () => void;
/** Navigate to specific slide index */
slideToIndex: (index: number, event?: SlideEvent) => void;
/** Get current slide index */
getCurrentIndex: () => number;
}
export interface UseGalleryNavigationProps {
items: GalleryItem[];
startIndex: number;
infinite: boolean;
isRTL: boolean;
slideDuration: number;
onSlide?: OnSlideCallback | null;
onBeforeSlide?: OnBeforeSlideCallback | null;
}
export interface UseGalleryNavigationReturn {
currentIndex: number;
previousIndex: number;
isTransitioning: boolean;
currentSlideOffset: number;
canSlideLeft: () => boolean;
canSlideRight: () => boolean;
slideToIndex: (index: number, event?: SlideEvent) => void;
slideToIndexCore: (index: number, event?: SlideEvent, isPlayPause?: boolean) => void;
slideToIndexWithStyleReset: (index: number, event?: SlideEvent) => void;
slideLeft: (event?: SlideEvent) => void;
slideRight: (event?: SlideEvent) => void;
getContainerStyle: (options?: ContainerStyleOptions) => CSSProperties;
getExtendedSlides: () => ExtendedSlidesResult;
getAlignmentClass: (displayIndex: number) => string;
setCurrentSlideOffset: (offset: number) => void;
setSlideStyle: (style: CSSProperties) => void;
}
export interface ContainerStyleOptions {
useTranslate3D?: boolean;
slideVertically?: boolean;
}
export interface ExtendedSlidesResult {
extendedItems: GalleryItem[];
getSlideKey: (displayIndex: number) => string;
getRealIndex: (displayIndex: number) => number;
}
export interface UseThumbnailsProps {
currentIndex: number;
items: GalleryItem[];
thumbnailPosition: ThumbnailPosition;
disableThumbnailScroll: boolean;
slideDuration: number;
isRTL: boolean;
useTranslate3D: boolean;
}
export interface UseThumbnailsReturn {
thumbsTranslate: number;
setThumbsTranslate: (value: number) => void;
thumbsSwipedTranslate: number;
setThumbsSwipedTranslate: (value: number) => void;
setThumbsStyle: (style: CSSProperties) => void;
thumbnailsWrapperWidth: number;
thumbnailsWrapperHeight: number;
isSwipingThumbnail: boolean;
setIsSwipingThumbnail: (value: boolean) => void;
thumbnailsWrapperRef: React.RefObject<HTMLDivElement | null>;
thumbnailsRef: React.RefObject<HTMLDivElement | null>;
isThumbnailVertical: () => boolean;
getThumbnailStyle: () => CSSProperties;
getThumbnailBarHeight: (gallerySlideWrapperHeight: number) => number | undefined;
initResizeObserver: (element: React.RefObject<HTMLElement | null>) => void;
removeResizeObserver: () => void;
}
export interface UseFullscreenProps {
useBrowserFullscreen: boolean;
onScreenChange?: OnScreenChangeCallback | null;
galleryRef: React.RefObject<HTMLDivElement | null>;
}
export interface UseFullscreenReturn {
isFullscreen: boolean;
modalFullscreen: boolean;
fullScreen: () => void;
exitFullScreen: () => void;
toggleFullScreen: () => void;
handleScreenChange: () => void;
}
export interface UseAutoPlayProps {
autoPlay: boolean;
slideInterval: number;
slideDuration: number;
infinite: boolean;
totalSlides: number;
currentIndex: number;
canSlideRight: () => boolean;
slideToIndexCore: (index: number, event?: SlideEvent, isPlayPause?: boolean) => void;
slideToIndexWithStyleReset: (index: number, event?: SlideEvent) => void;
onPlay?: OnPlayCallback | null;
onPause?: OnPauseCallback | null;
}
export interface UseAutoPlayReturn {
isPlaying: boolean;
playPauseIntervalRef: React.MutableRefObject<NodeJS.Timeout | null>;
play: () => void;
pause: () => void;
togglePlay: () => void;
}
export interface SlideProps {
alignment: string;
index: number;
originalClass: string;
onClick?: OnClickCallback | null;
onKeyUp?: (event: KeyboardEvent<HTMLDivElement>) => void;
onMouseLeave?: OnMouseCallback | null;
onMouseOver?: OnMouseCallback | null;
onTouchEnd?: OnTouchCallback | null;
onTouchMove?: OnTouchCallback | null;
onTouchStart?: OnTouchCallback | null;
children: ReactNode;
}
export interface ItemProps {
description?: string;
fullscreen?: string;
handleImageLoaded: (event: SyntheticEvent<HTMLImageElement>, original: string) => void;
isFullscreen: boolean;
loading?: "eager" | "lazy";
original: string;
originalAlt?: string;
originalHeight?: number;
originalTitle?: string;
originalWidth?: number;
sizes?: string;
srcSet?: string;
onImageError?: OnImageErrorCallback;
}
export interface ThumbnailProps {
index: number;
isActive: boolean;
thumbnailClass: string;
onClick: (event: MouseEvent<HTMLButtonElement>) => void;
onFocus: (event: React.FocusEvent<HTMLButtonElement>) => void;
onKeyUp: (event: KeyboardEvent<HTMLButtonElement>) => void;
onMouseLeave?: ((event: MouseEvent<HTMLButtonElement>) => void) | null;
onMouseOver: (event: MouseEvent<HTMLButtonElement>) => void;
children: ReactNode;
}
export interface ThumbnailBarProps {
disableThumbnailSwipe: boolean;
isRTL: boolean;
thumbnailBarHeight?: number;
thumbnailPosition: ThumbnailPosition;
thumbnails: ReactNode[];
thumbnailsRef: React.RefObject<HTMLDivElement | null>;
thumbnailStyle: CSSProperties;
thumbnailsWrapperRef: React.RefObject<HTMLDivElement | null>;
onSwiped: () => void;
onSwiping: (data: SwipeEventData) => void;
}
export interface BulletProps {
bulletClass?: string;
index: number;
isActive: boolean;
onClick: (event: MouseEvent<HTMLButtonElement>) => void;
}
export interface BulletNavProps {
bullets: ReactNode[];
slideVertically: boolean;
}
export interface IndexIndicatorProps {
currentIndex: number;
indexSeparator: string;
totalItems: number;
}
export interface NavButtonProps {
disabled: boolean;
onClick: (event: MouseEvent<HTMLButtonElement>) => void;
}
export interface PlayPauseProps {
isPlaying: boolean;
onClick: () => void;
}
export interface FullscreenProps {
isFullscreen: boolean;
onClick: () => void;
}
export interface SwipeWrapperProps {
className?: string;
delta?: number;
onSwiped: (data: SwipeEventData) => void;
onSwiping: (data: SwipeEventData) => void;
children: ReactNode;
}
export interface SwipeEventData {
event: globalThis.TouchEvent | globalThis.MouseEvent;
absX: number;
absY: number;
dir: SwipeDirection;
velocity: number;
}
export type SwipeDirection = "Left" | "Right" | "Up" | "Down";
export interface SVGProps {
strokeWidth?: number;
}
declare const ImageGallery: React.ForwardRefExoticComponent<ImageGalleryProps & React.RefAttributes<ImageGalleryRef>>;
export default ImageGallery;