import type { ReactNode } from "react"; import type { ProductMedia } from "../Commerce/commerceTypes"; import type { MediaLightboxLabels } from "./MediaLightboxProps"; /** `auto` picks `thumbs-left` when the gallery is at least 560px wide (viewport 768px until measured) and `swipe` below that. */ export type MediaGalleryLayout = "auto" | "thumbs-left" | "thumbs-below" | "swipe"; /** `lightbox` opens the full-screen viewer, `inner` zooms in place, `none` is inert. */ export type MediaGalleryZoom = "lightbox" | "inner" | "none"; /** Width / height of the media well; every frame is cropped to it, never stretched. */ export type MediaAspectRatio = "4/5" | "1/1" | "3/4" | "16/9" | `${number}/${number}`; /** Every string the gallery renders or announces, merged over `defaultMediaGalleryLabels`. */ export interface MediaGalleryLabels { /** Accessible name of the carousel region. */ region: string; /** Slide label, "2 of 5". */ slide: (position: number, total: number) => string; /** Alt text for a frame that has no `alt` of its own. */ image: (position: number, total: number) => string; /** Accessible name of a thumbnail or dot; `alt` is the frame's own description when it has one. */ frame: (position: number, total: number, alt?: string) => string; /** Accessible name of the previous-frame arrow. */ previous: string; /** Accessible name of the next-frame arrow. */ next: string; /** Accessible name of the dots group. */ dots: string; /** Accessible name of the thumbnail list. */ thumbnails: string; /** Visible and live-announced counter, "1 / 5". */ counter: (position: number, total: number) => string; /** Pill shown on desktop while `zoom` is not `none`. */ zoomHint: string; /** Name of the button that opens the lightbox on an image. */ openLightbox: (position: number, total: number) => string; /** Name of the button that toggles in-place zoom on an image. */ zoomImage: (position: number, total: number) => string; /** Accessible name of the play button over a video frame. */ playVideo: string; /** Shown in place of an image that fails to load. */ imageUnavailable: string; /** Accessible name of the skeleton shown while `isLoading`. */ loading: string; } export declare const defaultMediaGalleryLabels: MediaGalleryLabels; /** Product media carousel: thumbnail rail or swipe track, lightbox, colour-linked frames. */ export interface MediaGalleryProps { /** Every frame the product has; images are cropped to `aspectRatio`, videos play on demand. */ media: ProductMedia[]; /** Arrangement of well and thumbnails; `auto` shows the thumbnail rail from 560px of the gallery's own width. */ layout?: MediaGalleryLayout; /** Shape of the well. */ aspectRatio?: MediaAspectRatio; /** What a click on an image does. */ zoom?: MediaGalleryZoom; /** Controlled frame position, within the visible frames; pair with `onIndexChange`. */ index?: number; /** Starting frame when uncontrolled. */ defaultIndex?: number; /** Fires on every navigation (swipe, key, arrow, thumbnail, dot) with the new position. */ onIndexChange?: (index: number) => void; /** Restricts and orders the visible frames by media id, e.g. the selected colour's `mediaIds`; position resets to 0. */ activeMediaIds?: string[]; /** Overlaid top-left on the well, e.g. product badges. */ badges?: ReactNode; /** Overlaid top-right on the well, e.g. a wishlist toggle. */ actions?: ReactNode; /** Pins the gallery while the rest of the page scrolls past. */ sticky?: boolean; /** Offset from the top of the viewport when `sticky`, in px. */ stickyTop?: number; /** Square the corners for an edge-to-edge well; defaults to rounded except in the swipe layout. */ rounded?: boolean; /** Renders a skeleton of the same shape in place of the frames. */ isLoading?: boolean; /** Overrides for any of `defaultMediaGalleryLabels`. */ labels?: Partial; /** Overrides for the lightbox copy. */ lightboxLabels?: Partial; /** Replaces `labels.region` as the carousel's accessible name, e.g. the product title. */ "aria-label"?: string; /** Test id on the gallery's root element. */ "data-testid"?: string; }