UNPKG

astro-lightgallery

Version:

Astro component for lightgallery, JavaScript gallery for building beautiful image and video galleries and carousel (including thumbnail) for the web and the mobile

214 lines (188 loc) 8.18 kB
// Copyright (c) Pascal Brand // MIT License import ligthGallery from 'lightgallery' import type { LightGallerySettings } from 'lightgallery/lg-settings'; import type { HTMLAttributes } from 'astro/types' import type { LgQuery } from 'lightgallery/lgQuery' import type { LightGallery } from 'lightgallery/lightgallery'; export type AstroLightGalleryPluginStrType = ( 'thumbnail' | 'autoplay' | 'comment' | 'fullscreen' | 'hash' | 'mediumZoom' | 'pager' | 'relativeCaption' | 'rotate' | 'share' | 'video' | 'vimeoThumbnail' | 'zoom' ) /** * Fix in atro-lightgallery missing plugin settings in LightGallerySettings * TODO: Once fixed in lightgallery (cf. PR https://github.com/sachinchoolur/lightGallery/pull/1724), * LightGallerySettingsFix can be removed from options types. * * This new type LightGallerySettingsFix is not exported on purpose, to avoid * using it directly as it should be removed once lightgallery is updated. * LightGallerySettings must be used instead in external applications */ import type { LightGalleryAllSettings } from 'lightgallery/lg-settings'; import type { RelativeCaptionSettings } from 'lightgallery/plugins/relativeCaption/lg-relative-caption-settings'; import type { VimeoThumbnailSettings } from 'lightgallery/plugins/vimeoThumbnail/lg-vimeo-thumbnail-settings'; type LightGalleryAllSettingsFix = LightGalleryAllSettings & RelativeCaptionSettings & VimeoThumbnailSettings; type LightGallerySettingsFix = Partial<LightGalleryAllSettingsFix>; /** List of images, and their attributes, to be displayed in a provided layout */ export interface AstroLightGalleryImgType { /** the source of the large image */ src: string, /** the source of the thumbnail image. If not provided, use src (the large one) */ srcThumb?: string /** alt of the image */ alt?: string /* caption for the slide, if any */ subHtml?:string } /** Layout parameters, when the user wants to use an existing layout * for the whole gallery. * It contains the images of the gallery, the parameters of the chosen * layout, ... */ export interface AstroLightGalleryLayoutType { /** images to be displayed in the gallery */ imgs: AstroLightGalleryImgType[], /** adaptive layout parameters. This is the default layout */ adaptive?: { /** zoom factor (100 by default) to enlarge or reduce the gallery * with respect to the original size provided by the layout */ zoom?:number, } /** classContainer, to be defined by the user in case he wants * to enrich the layout default container */ classContainer?: string, /** classItem to be defined by the user in case he wants * to enrich the layout default item, for example with hover effect... */ classItem?: string, } /** properties passed to the <LightGallery> component * It extends a div (that is may have class, style,...), plus other attributes */ export interface AstroLightGalleryType extends HTMLAttributes<"div"> { /** lightgallery options, to set autoplay, navigation, thumbnails,... * check fullset of options: https://www.lightgalleryjs.com/docs/settings */ options?: LightGallerySettings | LightGallerySettingsFix, /** plugins to be added manually (such as zoom). * note that when possible, the plugins are automatically detected * (for example when thumbnail=true in the options) */ addPlugins?: AstroLightGalleryPluginStrType[], /** to ease user experience, some default layouts are provided. * This ease the lightgallery usage, as only the image list and their attributes * has to be provided */ layout?: AstroLightGalleryLayoutType, } /** astro components exported, used to create a lightgallery */ export { default as LightGallery } from './components/LightGallery.astro' function _textColor(text: string, color: string) { let colorCode: string if (color === 'FgRed') { colorCode = '\x1b[31m' } else if (color === 'FgBlue') { colorCode = '\x1b[34m' } else if (color === 'FgGreen') { colorCode = '\x1b[32m' } else if (color === 'FgYellow') { colorCode = '\x1b[33m' } else if (color === 'FgCyan') { colorCode = '\x1b[36m' } else { colorCode = '\x1b[31m' } // red by default return colorCode + text + '\x1b[0m' } async function _addPlugin(plugins: (new (instance: LightGallery, $LG: LgQuery) => any)[], pluginStr: AstroLightGalleryPluginStrType) { console.log(_textColor(`astro-lightgallery: add plugin ${pluginStr}`, 'FgGreen')) let plugin= undefined switch (pluginStr) { case 'thumbnail': plugin = await import('lightgallery/plugins/thumbnail') break case 'autoplay': plugin = await import('lightgallery/plugins/autoplay') break case 'comment': plugin = await import('lightgallery/plugins/comment') break case 'fullscreen': plugin = await import('lightgallery/plugins/fullscreen') break case 'hash': plugin = await import('lightgallery/plugins/hash') break case 'mediumZoom': plugin = await import('lightgallery/plugins/mediumZoom') break case 'pager': plugin = await import('lightgallery/plugins/pager') break case 'relativeCaption': plugin = await import('lightgallery/plugins/relativeCaption') break case 'rotate': plugin = await import('lightgallery/plugins/rotate') break case 'share': plugin = await import('lightgallery/plugins/share') break case 'video': plugin = await import('lightgallery/plugins/video') break case 'vimeoThumbnail': plugin = await import('lightgallery/plugins/vimeoThumbnail') break case 'zoom': plugin = await import('lightgallery/plugins/zoom') break default: console.log(_textColor(`astro-lightgallery: failed adding unknown plugin ${pluginStr}`, 'FgRed')) break } if (plugin !== undefined) { plugins.push(plugin.default) } } export async function createLightGallery(id: string, options: LightGallerySettings, addPlugins: AstroLightGalleryPluginStrType[]): Promise<LightGallery | undefined> { const plugins: (new (instance: LightGallery, $LG: LgQuery) => any)[] = [] const el = document.getElementById(id) if (!el) { return undefined } // automatic add plugins if (options.autoplay!==undefined) { addPlugins.push('autoplay') } // if (options.comment !== undefined) { addPlugins.push('comment') } if (options.fullScreen !== undefined) { addPlugins.push('fullscreen') } if (options.hash !== undefined) { addPlugins.push('hash') } if (options.mediumZoom !== undefined) { addPlugins.push('mediumZoom') } if (options.pager !== undefined) { addPlugins.push('pager') } // if (options.relativeCaption !== undefined) { addPlugins.push('relativeCaption') } if (options.rotate !== undefined) { addPlugins.push('rotate') } if (options.share !== undefined) { addPlugins.push('share') } if ((options.thumbnail!==undefined) || (options.animateThumb!==undefined)) { addPlugins.push('thumbnail') } // if (options.video !== undefined) { addPlugins.push('video') } // if (options.showVimeoThumbnails !== undefined) { addPlugins.push('vimeoThumbnail') } if (options.zoom !== undefined) { addPlugins.push('zoom') } // remove duplicates addPlugins = [... new Set(addPlugins)] // add plugins await Promise.all(addPlugins.map(async (pluginStr) => await _addPlugin(plugins, pluginStr))) options.plugins = plugins const gallery = ligthGallery(el, options) return gallery } declare class AstroLightgallery extends HTMLElement { /** pointer to the Lightgallery structure that was created using "new", * even when not initialized */ astroLightGallery: Promise<LightGallery | undefined> | undefined } export function getLightGalleryFromUniqueSelector(uniqueSelector: string): Promise<LightGallery | undefined> | undefined { return (document.querySelector(uniqueSelector) as AstroLightgallery)?.astroLightGallery }