import React from 'react';

/** Layout type */
type LayoutType = "rows" | "columns" | "masonry";
/** Photo object */
interface Photo extends Image {
    /** React `key` attribute. */
    key?: string;
    /** Image `alt` attribute. */
    alt?: string;
    /** Image `title` attribute. */
    title?: string;
    /** Image link URL. */
    href?: string;
    /** ARIA label for the link and button elements */
    label?: string;
    /** Optional array of alternative images to be included in the `srcset` attribute. */
    srcSet?: readonly Image[];
}
/** Image object */
interface Image {
    /** Image source. */
    src: string;
    /** Image width in pixels. */
    width: number;
    /** Image height in pixels. */
    height: number;
}
/** Common photo album props */
interface CommonPhotoAlbumProps<TPhoto extends Photo = Photo> {
    /** An array of photos to display in the photo album. */
    photos: readonly TPhoto[];
    /** Spacing between images. */
    spacing?: ResponsiveParameter;
    /** Padding around each image. */
    padding?: ResponsiveParameter;
    /** Photo album container width in various viewports. */
    sizes?: ResponsiveSizes;
    /** Photo album layout breakpoints. */
    breakpoints?: readonly number[];
    /** Default container width in SSR. */
    defaultContainerWidth?: number;
    /** Photo click callback. */
    onClick?: ClickHandler<TPhoto>;
    /** Custom render functions. */
    render?: ResponsiveParameter<Render<TPhoto>, number | undefined>;
    /** Additional HTML attributes to be passed to the rendered elements. */
    componentsProps?: ResponsiveParameter<ComponentsProps<TPhoto>, number | undefined>;
    /** Fallback skeleton in SSR. */
    skeleton?: React.ReactNode;
}
/** Rows photo album props */
interface RowsPhotoAlbumProps<TPhoto extends Photo = Photo> extends CommonPhotoAlbumProps<TPhoto> {
    /** Target row height. */
    targetRowHeight?: ResponsiveParameter;
    /** Additional row constraints. */
    rowConstraints?: ResponsiveParameter<RowConstraints>;
}
/** Columns photo album props */
interface ColumnsPhotoAlbumProps<TPhoto extends Photo = Photo> extends CommonPhotoAlbumProps<TPhoto> {
    /** Number of columns. */
    columns?: ResponsiveParameter;
}
/** Masonry photo album props */
interface MasonryPhotoAlbumProps<TPhoto extends Photo = Photo> extends ColumnsPhotoAlbumProps<TPhoto> {
}
/** Photo album sizes settings */
type ResponsiveSizes = {
    /** Default size, e.g. `100vw` or `calc(100vw - 200px)`. */
    size: string;
    /** Array of sizes at various breakpoints. */
    sizes?: readonly {
        /** Viewport size media query, e.g. `(max-width: 600px)`.  */
        viewport: string;
        /** Photo album width at a given viewport size, e.g. `calc(100vw - 50px)`. */
        size: string;
    }[];
};
/** Row constraints */
type RowConstraints = {
    /** Minimum number of photos per row. */
    minPhotos?: number;
    /** Maximum number of photos per row. */
    maxPhotos?: number;
    /** Maximum row height when there is not enough photos to fill more than one row. */
    singleRowMaxHeight?: number;
};
/** Layout model */
type LayoutModel<TPhoto extends Photo = Photo> = {
    /** Spacing value. */
    spacing: number;
    /** Padding value. */
    padding: number;
    /** Container width. */
    containerWidth: number;
    /** Layout variables. */
    variables?: LayoutVariables;
    /** Layout orientation. */
    horizontal?: boolean;
    /** Layout tracks. */
    tracks: readonly {
        /** Track variables. */
        variables?: LayoutVariables;
        /** Photos array. */
        photos: readonly {
            /** Photo object. */
            photo: TPhoto;
            /** Photo index in the original `photos` array. */
            index: number;
            /** Rendered photo width in pixels. */
            width: number;
            /** Rendered photo height in pixels. */
            height: number;
        }[];
    }[];
};
/** Layout variables */
type LayoutVariables = Record<string, string | number | undefined>;
/** Responsive parameter */
type ResponsiveParameter<Value = number, ContainerWidth = number> = ((containerWidth: ContainerWidth) => Value) | Value;
/** Components props */
type ComponentsProps<TPhoto extends Photo = Photo> = {
    /** Additional HTML attributes for the outer `<div>` container. */
    container?: ContainerComponentProps;
    /** Additional HTML attributes for the row / column `<div>` container. */
    track?: TrackComponentProps;
    /** Additional HTML attributes for the image `<div>` wrapper. */
    wrapper?: WrapperComponentProps<TPhoto>;
    /** Additional HTML attributes for the photo `<a>` link. */
    link?: LinkComponentProps<TPhoto>;
    /** Additional HTML attributes for the photo `<button>` element. */
    button?: ButtonComponentProps<TPhoto>;
    /** Additional HTML attributes for the photo `<img>` element. */
    image?: ImageComponentProps<TPhoto>;
};
/** Container component props */
type ContainerComponentProps = React.ComponentPropsWithoutRef<"div">;
/** Track component props */
type TrackComponentProps = React.ComponentPropsWithoutRef<"div">;
/** Wrapper component props */
type WrapperComponentProps<TPhoto extends Photo = Photo> = ContextAware<React.ComponentPropsWithoutRef<"div">, RenderWrapperContext<TPhoto>>;
/** Link component props */
type LinkComponentProps<TPhoto extends Photo = Photo> = ContextAware<React.ComponentPropsWithoutRef<"a">, RenderLinkContext<TPhoto>>;
/** Button component props */
type ButtonComponentProps<TPhoto extends Photo = Photo> = ContextAware<React.ComponentPropsWithoutRef<"button">, RenderButtonContext<TPhoto>>;
/** Image component props */
type ImageComponentProps<TPhoto extends Photo = Photo> = ContextAware<React.ComponentPropsWithoutRef<"img">, RenderImageContext<TPhoto>>;
/** Click handler */
type ClickHandler<TPhoto extends Photo = Photo> = (props: ClickHandlerProps<TPhoto>) => void;
/** Click callback props */
type ClickHandlerProps<TPhoto extends Photo = Photo> = {
    /** Click event. */
    event: React.MouseEvent;
    /** Photo object. */
    photo: TPhoto;
    /** Photo index in the original `photos` array. */
    index: number;
};
/** Custom render functions */
type Render<TPhoto extends Photo = Photo> = {
    /** Custom container render function. */
    container?: RenderContainer;
    /** Custom track render function. */
    track?: RenderTrack;
    /** Custom wrapper render function. */
    wrapper?: RenderWrapper<TPhoto>;
    /** Custom link render function. */
    link?: RenderLink<TPhoto>;
    /** Custom button render function. */
    button?: RenderButton<TPhoto>;
    /** Custom image render function. */
    image?: RenderImage<TPhoto>;
    /** Custom photo render function. */
    photo?: RenderPhoto<TPhoto>;
    /** Custom extra markup render function. */
    extras?: RenderExtras<TPhoto>;
};
/** Render container */
type RenderContainer = RenderFunction<RenderContainerProps>;
/** Render container props */
type RenderContainerProps = React.ComponentPropsWithRef<"div">;
/** Render track */
type RenderTrack = RenderFunction<RenderTrackProps>;
/** Render track props */
type RenderTrackProps = React.ComponentPropsWithoutRef<"div">;
/** Render wrapper */
type RenderWrapper<TPhoto extends Photo = Photo> = RenderFunction<RenderWrapperProps, RenderWrapperContext<TPhoto>>;
/** Render wrapper props */
type RenderWrapperProps = React.ComponentPropsWithoutRef<"div">;
/** Render wrapper context */
type RenderWrapperContext<TPhoto extends Photo = Photo> = RenderPhotoContext<TPhoto>;
/** Render link */
type RenderLink<TPhoto extends Photo = Photo> = RenderFunction<RenderLinkProps, RenderLinkContext<TPhoto>>;
/** Render link props */
type RenderLinkProps = NonOptional<React.ComponentPropsWithoutRef<"a">, "href">;
/** Render link context */
type RenderLinkContext<TPhoto extends Photo = Photo> = RenderPhotoContext<TPhoto>;
/** Render button */
type RenderButton<TPhoto extends Photo = Photo> = RenderFunction<RenderButtonProps, RenderButtonContext<TPhoto>>;
/** Render button props */
type RenderButtonProps = React.ComponentPropsWithoutRef<"button">;
/** Render button context */
type RenderButtonContext<TPhoto extends Photo = Photo> = RenderPhotoContext<TPhoto>;
/** Render image */
type RenderImage<TPhoto extends Photo = Photo> = RenderFunction<RenderImageProps, RenderImageContext<TPhoto>>;
/** Render image props */
type RenderImageProps = NonOptional<React.ComponentPropsWithoutRef<"img">, "src">;
/** Render image context */
type RenderImageContext<TPhoto extends Photo = Photo> = RenderPhotoContext<TPhoto>;
/** Render photo */
type RenderPhoto<TPhoto extends Photo = Photo> = RenderFunction<RenderPhotoProps, RenderPhotoContext<TPhoto>>;
/** Render photo props */
type RenderPhotoProps = {
    /** Click callback. */
    onClick?: React.MouseEventHandler;
};
/** Render photo context */
type RenderPhotoContext<TPhoto extends Photo = Photo> = {
    /** Photo object. */
    photo: TPhoto;
    /** Photo index in the original `photos` array. */
    index: number;
    /** Rendered photo width in pixels. */
    width: number;
    /** Rendered photo height in pixels. */
    height: number;
};
/** Render extras */
type RenderExtras<TPhoto extends Photo = Photo> = RenderFunction<object, RenderPhotoContext<TPhoto>>;
/** Render function */
type RenderFunction<Props extends object | void = void, Context extends object | void = void> = [
    Context
] extends [void] ? [Props] extends [void] ? () => React.ReactNode : (
/** Component props. */
props: Props) => React.ReactNode : [Props] extends [void] ? never : (
/** Component props. */
props: Props, 
/** Rendering context. */
context: Context) => React.ReactNode;
type ResolvedNumber<TWidth extends number | undefined = number | undefined> = TWidth extends number ? number : number | undefined;
type NonOptional<Props, Keys extends keyof Props> = Required<Pick<Props, Keys>> & Omit<Props, Keys>;
type ContextAware<Props, Context> = Props | ((context: Context) => Props | undefined);
type JSXElement = React.JSX.Element;
type ForwardedRef<T extends HTMLElement = HTMLElement> = React.ForwardedRef<T>;
type ElementRef<T extends HTMLElement = HTMLElement> = {
    ref?: React.Ref<T>;
};

export type { ButtonComponentProps, ClickHandler, ClickHandlerProps, ColumnsPhotoAlbumProps, CommonPhotoAlbumProps, ComponentsProps, ContainerComponentProps, ContextAware, ElementRef, ForwardedRef, Image, ImageComponentProps, JSXElement, LayoutModel, LayoutType, LayoutVariables, LinkComponentProps, MasonryPhotoAlbumProps, NonOptional, Photo, Render, RenderButton, RenderButtonContext, RenderButtonProps, RenderContainer, RenderContainerProps, RenderExtras, RenderFunction, RenderImage, RenderImageContext, RenderImageProps, RenderLink, RenderLinkContext, RenderLinkProps, RenderPhoto, RenderPhotoContext, RenderPhotoProps, RenderTrack, RenderTrackProps, RenderWrapper, RenderWrapperContext, RenderWrapperProps, ResolvedNumber, ResponsiveParameter, ResponsiveSizes, RowConstraints, RowsPhotoAlbumProps, TrackComponentProps, WrapperComponentProps };
