import { PhotoSwipeOptions } from 'photoswipe'; import PhotoSwipeLightbox from 'photoswipe/lightbox'; declare interface ItemOptions { lightbox?: boolean; selectable?: boolean; activable?: boolean; gap?: number; showLabels?: 'hover' | 'never' | 'always'; } declare class Item<Model extends ModelAttributes> { private readonly document; private readonly options; readonly model: Model; /** * Cleaned title, used for label / button */ readonly title: string; /** * Actual row index in the list */ private _row; /** * If is actually the last element of a row */ private _last; /** * Computed size (real used size) */ private _width; private _height; private _cropped; /** * Wherever item is selected or not * @type {boolean} * @private */ private _selected; /** * Item root element reference (figure) */ private _element; /** * Image container reference (child div, containing the image) */ private _image; /** * Reference to the select button */ private _selectBtn; /** * Element referering the "button" containing the label */ private label; /** * * @param {ItemOptions} options * @param model Contains the source data given for an item (e.g object instance from database with id etc..) */ constructor(document: Document, options: ItemOptions, model: Model); /** * Cleans html, and returns only the text from all eventual tags * @param {string} term * @returns {ItemTitle} */ private getTitleDetails; /** * Create DOM elements according to element raw data (thumbnail and enlarged urls) * Also apply border-radius at this level because it never changed threw time */ init(): HTMLElement; setLabelHover(activate: boolean): void; /** * Use computed (organized) data to apply style (size and margin) to elements on DOM * Does not apply border-radius because is used to restyle data on browser resize, and border-radius don't change. */ style(): void; /** * This function prepare loaded/loading status and return root element. * @returns {HTMLElement} */ loadImage(): void; toggleSelect(): void; select(): void; unselect(): void; private getLinkElement; remove(): void; get last(): boolean; set last(value: boolean); get row(): number; set row(value: number); get height(): number; set height(value: number); get width(): number; set width(value: number); get cropped(): boolean; set cropped(value: boolean); get enlargedWidth(): number; get enlargedHeight(): number; get selected(): boolean; get element(): HTMLElement; } /** * A map of all possible event and the structure of their details */ interface CustomEventDetailMap<T> { 'activate': { model: T; clickEvent: MouseEvent; }; 'item-added-to-dom': T; 'item-displayed': T; 'pagination': { offset: number; limit: number; }; 'select': T[]; } /** * Augment the global namespace with our custom events * See: https://github.com/Microsoft/TypeScript/issues/28357 */ declare global { interface HTMLElementEventMap { activate: CustomEvent; 'item-added-to-dom': CustomEvent; 'item-displayed': CustomEvent; pagination: CustomEvent; select: CustomEvent; } } interface SizedModel { /** * Height in pixels of the enlarged version the image * If photoswipe is used, the size of the photoswipe enlarged image is required * If photoswipe is not used, any size that match the ratio is enough */ enlargedWidth: number; /** * Width in pixels of the enlarged version the image * If photoswipe is used, the size of the photoswipe enlarged image is required * If photoswipe is not used, any size that match the ratio is enough */ enlargedHeight: number; } interface ModelAttributes extends SizedModel { /** * Source link for thumbnail image */ thumbnailSrc: string; /** * Source link for enlarged (photoswipe) image */ enlargedSrc?: string; /** * Label of item (or button) */ title?: string; /** * Href link */ link?: string; /** * a href target attribute */ linkTarget?: '_blank' | '_self' | '_parent' | '_top'; /** * Hex color */ color?: string; /** * If item is selected */ selected?: boolean; /** * Background size, default : cover */ backgroundSize?: string; /** * Background position, default : center */ backgroundPosition?: string; } interface GalleryOptions extends ItemOptions { rowsPerPage?: number; minRowsAtStart?: number; infiniteScrollOffset?: number; photoSwipeOptions?: PhotoSwipeOptions; photoSwipePluginsInitFn?: ((lighbox: PhotoSwipeLightbox) => void) | null; ssr?: { /** * In SSR mode, if the gallery width cannot be computed, it will fallback to this value */ galleryWidth: number; }; } declare abstract class AbstractGallery<Model extends ModelAttributes> { protected elementRef: HTMLElement; protected scrollElementRef?: HTMLElement | null | undefined; /** * Default options */ protected options: Required<GalleryOptions>; /** * Images wrapper container * If setted, serves as mark for "initialized status" of the gallery */ protected bodyElementRef: HTMLElement | null; /** * Items for which container has been added to dom, but image has not been queries yet */ protected scrollBufferedItems: Item<Model>[]; /** * Debounce function * Runs a small delay after last image has been added to dom * When it runs, images are loaded (appear with fade) and more images are queries to preserve a buffer of * out-of-dom items */ protected flushBufferedItems: () => void; /** * Number of items to query on buffer flushing */ protected requiredItems: number; /** * Used to test the scroll direction * Avoid to load more images when scrolling up */ private old_scroll_top; /** * Stores page index that have been emmited * Keeps a log of pages already asked to prevent to ask them multiple times */ private requestedIndexesLog; /** * Reference to next button element */ private nextButton; protected readonly document: Document; /** * PhotoSwipe Lightbox object */ protected psLightbox: PhotoSwipeLightbox | null; /** * Get PhotoSwipe Lightbox */ get photoSwipe(): PhotoSwipeLightbox | null; /** * Get currently selected PhotoSwipe image */ get photoSwipeCurrentItem(): Model | null; /** * * @param elementRef * @param options * @param scrollElementRef */ constructor(elementRef: HTMLElement, options: GalleryOptions, scrollElementRef?: HTMLElement | null | undefined); /** * Complete collection of images * @type {Array} */ protected _collection: Item<Model>[]; get collection(): Item<Model>[]; /** * Partial set of items that represent the visible items * @type {Item[]} * @private */ protected _domCollection: Item<Model>[]; get domCollection(): Item<Model>[]; get selectedItems(): Model[]; get width(): number; get collectionLength(): number; get domCollectionLength(): number; /** * Initializes DOM manipulations */ init(): void; /** * Initializes PhotoSwipe */ protected photoSwipeInit(): void; addItemToPhotoSwipeCollection(item: Item<Model>): void; /** * Add items to collection * Transform given list of models into inner Items * @param models list of models */ addItems(models: Model[]): void; setLabelHover(activate: boolean): void; /** * Select all items visible in the DOM * Ignores buffered items */ selectVisibleItems(): Model[]; /** * Unselect all selected elements */ unselectAllItems(): void; /** * Allows to use the same approach and method name to listen as gallery events on DOM or on javascript gallery * object * * Gallery requests items when it's instantiated. But user may subscribe after creation, so we need to request * again if user subscribes by this function. * * @param name * @param callback * @param options An object that specifies characteristics about the event listener. The available options are, see * addEventListener official documentation */ addEventListener<K extends keyof CustomEventDetailMap<Model>>(name: K, callback: (evt: CustomEvent<CustomEventDetailMap<Model>[K]>) => void, options?: boolean | AddEventListenerOptions): void; /** * Public api for empty function * Emits a pagination event */ clear(): void; /** * Return copy of options to prevent modification */ getOptions(): GalleryOptions; /** * Override current collection * @param {Item[]} items */ setItems(items: Model[]): void; /** * */ abstract organizeItems(items: Item<Model>[], fromRow?: number, toRow?: number): void; /** * If gallery already has items on initialisation, set first page visible, load second page and query for more * items if needed. * If not, just query for items */ protected initItems(): void; /** * */ protected abstract getEstimatedColumnsPerRow(): number; /** * AbstractRowGallery + Masonry */ protected abstract onScroll(): void; /** * AbstractRowGallery + Masonry */ protected abstract onPageAdd(): void; /** * Return number of rows to show per page to fill the empty space until the bottom of the screen * Should grant all the space is used or more, but not less. * @returns {number} */ protected abstract getEstimatedRowsPerPage(): number; /** * Fire pagination event * Information provided in the event allows to retrieve items from the server using given data : * "offset" and "limit" that have the same semantic that respective attributes in mySQL. * * The gallery asks for items it needs, including some buffer items that are not displayed when given but are * available to be added immediately to DOM when user scrolls. * */ protected requestItems(): void; /** * Returns option.rowsPerPage is specified. * If not returns the estimated number of rows to fill the rest of the vertical space in the screen * @returns {number} */ protected getRowsPerPage(): number; /** * Add given item to DOM and to domCollection * @param {Item} item * @param destination */ protected addItemToDOM(item: Item<Model>, destination?: HTMLElement | null): void; protected updateNextButtonVisibility(): void; /** * If infinite scroll (no option.rowsPerPage provided), a minimum height is setted to force gallery to overflow * from viewport. This activates the scroll before adding items to dom. This prevents the scroll to fire new resize * event and recompute all gallery twice on start. */ protected extendToFreeViewport(): void; /** * Space between the top of the gallery wrapper (parent of gallery root elementRef) and the bottom of the window */ protected getGalleryVisibleHeight(): number; protected startResize(): void; protected endResize(): void; protected dispatchEvent<K extends keyof CustomEventDetailMap<Model>>(name: K, data: CustomEventDetailMap<Model>[K]): void; /** * Effectively empty gallery, and should prepare container to receive new items */ protected empty(): void; /** * Listen to scroll event and manages rows additions for lazy load * @param {HTMLElement | Document} element */ private bindScroll; } interface RatioLimits { min?: number; max?: number; } declare abstract class AbstractRowGallery<Model extends ModelAttributes> extends AbstractGallery<Model> { protected onScroll(): void; protected onPageAdd(): void; /** * Add given number of rows to DOM * @param rows */ protected addRows(rows: number): void; protected endResize(): void; } interface NaturalGalleryOptions extends GalleryOptions { rowHeight: number; ratioLimit?: RatioLimits; } declare class Natural<Model extends ModelAttributes = ModelAttributes> extends AbstractRowGallery<Model> { /** * Options after having been defaulted */ protected options: Required<NaturalGalleryOptions>; constructor(elementRef: HTMLElement, options: NaturalGalleryOptions, scrollElementRef?: HTMLElement | null); static organizeItems<T extends ModelAttributes>(gallery: Natural<T>, items: Item<T>[], fromRow?: number, toRow?: number | null, currentRow?: number | null): void; /** * Compute sizes for given images to fit in given row width * Items are updated */ static computeSizes<T extends ModelAttributes>(chunk: Item<T>[], containerWidth: number | null, margin: number, row: number, maxRowHeight?: number | null, ratioLimits?: RatioLimits): void; static getRowWidth(models: SizedModel[], maxRowHeight: number, margin: number, ratioLimits?: RatioLimits): number; static getRowHeight(models: SizedModel[], containerWidth: number, margin: number, ratioLimits?: RatioLimits): number; /** * Return the ratio format of models as if they where a single image */ static getRatios(models: SizedModel[], ratioLimits?: RatioLimits): number; addRows(rows: number): void; organizeItems(items: Item<Model>[], fromRow?: number, toRow?: number): void; protected endResize(): void; protected getEstimatedColumnsPerRow(): number; protected getEstimatedRowsPerPage(): number; private completeLastRow; } declare interface ColumnOptions { width: number; gap: number; } declare class Column<Model extends ModelAttributes> { private options; private readonly collection; private readonly _elementRef; constructor(document: Document, options: ColumnOptions); addItem(item: Item<Model>): void; get height(): number; get length(): number; get elementRef(): HTMLElement; } interface MasonryGalleryOptions extends GalleryOptions { columnWidth: number; ratioLimit?: RatioLimits; } declare class Masonry<Model extends ModelAttributes = ModelAttributes> extends AbstractGallery<Model> { /** * Options after having been defaulted */ protected options: Required<MasonryGalleryOptions>; /** * Regroup the list of columns */ protected columns: Column<Model>[]; constructor(elementRef: HTMLElement, options: MasonryGalleryOptions, scrollElementRef?: HTMLElement | null); /** * Compute sides with 1:1 ratio */ static organizeItems<T extends ModelAttributes>(gallery: Masonry<T>, items: Item<T>[], fromIndex?: number, toIndex?: number | null): void; init(): void; organizeItems(items: Item<Model>[], fromRow?: number, toRow?: number): void; protected initItems(): void; protected onScroll(): void; protected onPageAdd(): void; protected getEstimatedColumnsPerRow(): number; protected getEstimatedRowsPerPage(): number; /** * Use current gallery height as reference. To fill free space it add images until the gallery height changes, then are one more row */ protected addUntilFill(): void; protected addItemToDOM(item: Item<Model>): void; protected endResize(): void; protected addColumns(): void; protected empty(): void; /** * Returns true if at least one columns doesn't overflow on the bottom of the viewport */ private viewPortIsNotFilled; private addItemsToDom; /** * Return square side size */ private getColumnWidth; private getShortestColumn; } interface SquareGalleryOptions extends GalleryOptions { itemsPerRow: number; } declare class Square<Model extends ModelAttributes = ModelAttributes> extends AbstractRowGallery<Model> { /** * Options after having been defaulted */ protected options: Required<SquareGalleryOptions>; constructor(elementRef: HTMLElement, options: SquareGalleryOptions, scrollElementRef?: HTMLElement | null); /** * Compute sides with 1:1 ratio */ static organizeItems<T extends ModelAttributes>(gallery: Square<T>, items: Item<T>[], firstRowIndex?: number, toRow?: number | null): void; protected getEstimatedColumnsPerRow(): number; protected getEstimatedRowsPerPage(): number; /** * Return square side size */ protected getItemSideSize(): number; organizeItems(items: Item<Model>[], fromRow?: number, toRow?: number): void; } export { type CustomEventDetailMap, Masonry, type MasonryGalleryOptions, type ModelAttributes, Natural, type NaturalGalleryOptions, Square, type SquareGalleryOptions };