{"version":3,"file":"1978.958b9a7527837fd26c44.js","mappings":"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","sources":["webpack://nationalspacecentre.web/../../../src/js/util/util.js","webpack://nationalspacecentre.web/../../../src/js/util/dom-events.js","webpack://nationalspacecentre.web/../../../src/js/util/viewport-size.js","webpack://nationalspacecentre.web/../../../src/js/slide/pan-bounds.js","webpack://nationalspacecentre.web/../../../src/js/slide/zoom-level.js","webpack://nationalspacecentre.web/../../../src/js/slide/slide.js","webpack://nationalspacecentre.web/../../../src/js/gestures/drag-handler.js","webpack://nationalspacecentre.web/../../../src/js/gestures/zoom-handler.js","webpack://nationalspacecentre.web/../../../src/js/gestures/tap-handler.js","webpack://nationalspacecentre.web/../../../src/js/gestures/gestures.js","webpack://nationalspacecentre.web/../../../src/js/main-scroll.js","webpack://nationalspacecentre.web/../../../src/js/keyboard.js","webpack://nationalspacecentre.web/../../../src/js/util/css-animation.js","webpack://nationalspacecentre.web/../../../src/js/util/spring-easer.js","webpack://nationalspacecentre.web/../../../src/js/util/spring-animation.js","webpack://nationalspacecentre.web/../../../src/js/util/animations.js","webpack://nationalspacecentre.web/../../../src/js/scroll-wheel.js","webpack://nationalspacecentre.web/../../../src/js/ui/ui-element.js","webpack://nationalspacecentre.web/../../../src/js/ui/button-arrow.js","webpack://nationalspacecentre.web/../../../src/js/ui/button-close.js","webpack://nationalspacecentre.web/../../../src/js/ui/button-zoom.js","webpack://nationalspacecentre.web/../../../src/js/ui/loading-indicator.js","webpack://nationalspacecentre.web/../../../src/js/ui/counter-indicator.js","webpack://nationalspacecentre.web/../../../src/js/ui/ui.js","webpack://nationalspacecentre.web/../../../src/js/core/eventable.js","webpack://nationalspacecentre.web/../../../src/js/slide/placeholder.js","webpack://nationalspacecentre.web/../../../src/js/slide/content.js","webpack://nationalspacecentre.web/../../../src/js/slide/loader.js","webpack://nationalspacecentre.web/../../../src/js/core/base.js","webpack://nationalspacecentre.web/../../../src/js/opener.js","webpack://nationalspacecentre.web/../../../src/js/photoswipe.js","webpack://nationalspacecentre.web/../../../src/js/slide/get-thumb-bounds.js"],"sourcesContent":["/** @typedef {import('../photoswipe.js').Point} Point */\r\n\r\n/** @typedef {undefined | null | false | '' | 0} Falsy */\r\n/** @typedef {keyof HTMLElementTagNameMap} HTMLElementTagName */\r\n\r\n/**\r\n * @template {HTMLElementTagName | Falsy} [T=\"div\"]\r\n * @template {Node | undefined} [NodeToAppendElementTo=undefined]\r\n * @param {string=} className\r\n * @param {T=} [tagName]\r\n * @param {NodeToAppendElementTo=} appendToEl\r\n * @returns {T extends HTMLElementTagName ? HTMLElementTagNameMap[T] : HTMLElementTagNameMap['div']}\r\n */\r\nexport function createElement(className, tagName, appendToEl) {\r\n const el = document.createElement(tagName || 'div');\r\n if (className) {\r\n el.className = className;\r\n }\r\n if (appendToEl) {\r\n appendToEl.appendChild(el);\r\n }\r\n // @ts-expect-error\r\n return el;\r\n}\r\n\r\n/**\r\n * @param {Point} p1\r\n * @param {Point} p2\r\n */\r\nexport function equalizePoints(p1, p2) {\r\n p1.x = p2.x;\r\n p1.y = p2.y;\r\n if (p2.id !== undefined) {\r\n p1.id = p2.id;\r\n }\r\n return p1;\r\n}\r\n\r\n/**\r\n * @param {Point} p\r\n */\r\nexport function roundPoint(p) {\r\n p.x = Math.round(p.x);\r\n p.y = Math.round(p.y);\r\n}\r\n\r\n/**\r\n * Returns distance between two points.\r\n *\r\n * @param {Point} p1\r\n * @param {Point} p2\r\n */\r\nexport function getDistanceBetween(p1, p2) {\r\n const x = Math.abs(p1.x - p2.x);\r\n const y = Math.abs(p1.y - p2.y);\r\n return Math.sqrt((x * x) + (y * y));\r\n}\r\n\r\n/**\r\n * Whether X and Y positions of points are qual\r\n *\r\n * @param {Point} p1\r\n * @param {Point} p2\r\n */\r\nexport function pointsEqual(p1, p2) {\r\n return p1.x === p2.x && p1.y === p2.y;\r\n}\r\n\r\n/**\r\n * The float result between the min and max values.\r\n *\r\n * @param {number} val\r\n * @param {number} min\r\n * @param {number} max\r\n */\r\nexport function clamp(val, min, max) {\r\n return Math.min(Math.max(val, min), max);\r\n}\r\n\r\n/**\r\n * Get transform string\r\n *\r\n * @param {number} x\r\n * @param {number=} y\r\n * @param {number=} scale\r\n */\r\nexport function toTransformString(x, y, scale) {\r\n let propValue = 'translate3d('\r\n + x + 'px,' + (y || 0) + 'px'\r\n + ',0)';\r\n\r\n if (scale !== undefined) {\r\n propValue += ' scale3d('\r\n + scale + ',' + scale\r\n + ',1)';\r\n }\r\n\r\n return propValue;\r\n}\r\n\r\n/**\r\n * Apply transform:translate(x, y) scale(scale) to element\r\n *\r\n * @param {HTMLElement} el\r\n * @param {number} x\r\n * @param {number=} y\r\n * @param {number=} scale\r\n */\r\nexport function setTransform(el, x, y, scale) {\r\n el.style.transform = toTransformString(x, y, scale);\r\n}\r\n\r\nconst defaultCSSEasing = 'cubic-bezier(.4,0,.22,1)';\r\n\r\n/**\r\n * Apply CSS transition to element\r\n *\r\n * @param {HTMLElement} el\r\n * @param {string=} prop CSS property to animate\r\n * @param {number=} duration in ms\r\n * @param {string=} ease CSS easing function\r\n */\r\nexport function setTransitionStyle(el, prop, duration, ease) {\r\n // inOut: 'cubic-bezier(.4, 0, .22, 1)', // for \"toggle state\" transitions\r\n // out: 'cubic-bezier(0, 0, .22, 1)', // for \"show\" transitions\r\n // in: 'cubic-bezier(.4, 0, 1, 1)'// for \"hide\" transitions\r\n el.style.transition = prop\r\n ? (prop + ' ' + duration + 'ms ' + (ease || defaultCSSEasing))\r\n : 'none';\r\n}\r\n\r\n/**\r\n * Apply width and height CSS properties to element\r\n *\r\n * @param {HTMLElement} el\r\n * @param {string | number} w\r\n * @param {string | number} h\r\n */\r\nexport function setWidthHeight(el, w, h) {\r\n el.style.width = (typeof w === 'number') ? (w + 'px') : w;\r\n el.style.height = (typeof h === 'number') ? (h + 'px') : h;\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n */\r\nexport function removeTransitionStyle(el) {\r\n setTransitionStyle(el);\r\n}\r\n\r\n/**\r\n * @param {HTMLImageElement} img\r\n * @returns {Promise}\r\n */\r\nexport function decodeImage(img) {\r\n if ('decode' in img) {\r\n return img.decode();\r\n }\r\n\r\n if (img.complete) {\r\n return Promise.resolve(img);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n img.onload = () => resolve(img);\r\n img.onerror = reject;\r\n });\r\n}\r\n\r\n/** @typedef {LOAD_STATE[keyof LOAD_STATE]} LoadState */\r\n/** @type {{ IDLE: 'idle'; LOADING: 'loading'; LOADED: 'loaded'; ERROR: 'error' }} */\r\nexport const LOAD_STATE = {\r\n IDLE: 'idle',\r\n LOADING: 'loading',\r\n LOADED: 'loaded',\r\n ERROR: 'error',\r\n};\r\n\r\n\r\n/**\r\n * Check if click or keydown event was dispatched\r\n * with a special key or via mouse wheel.\r\n *\r\n * @param {MouseEvent | KeyboardEvent} e\r\n */\r\nexport function specialKeyUsed(e) {\r\n if (e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) {\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Parse `gallery` or `children` options.\r\n *\r\n * @param {HTMLElement | NodeListOf | string} option\r\n * @param {string=} legacySelector\r\n * @param {HTMLElement | Document} [parent]\r\n * @returns HTMLElement[]\r\n */\r\nexport function getElementsFromOption(option, legacySelector, parent = document) {\r\n /** @type {HTMLElement[]} */\r\n let elements = [];\r\n\r\n if (option instanceof Element) {\r\n elements = [option];\r\n } else if (option instanceof NodeList || Array.isArray(option)) {\r\n elements = Array.from(option);\r\n } else {\r\n const selector = typeof option === 'string' ? option : legacySelector;\r\n if (selector) {\r\n elements = Array.from(parent.querySelectorAll(selector));\r\n }\r\n }\r\n\r\n return elements;\r\n}\r\n\r\n/**\r\n * Check if variable is PhotoSwipe class\r\n *\r\n * @param {any} fn\r\n */\r\nexport function isPswpClass(fn) {\r\n return typeof fn === 'function'\r\n && fn.prototype\r\n && fn.prototype.goTo;\r\n}\r\n\r\n/**\r\n * Check if browser is Safari\r\n *\r\n * @returns {boolean}\r\n */\r\nexport function isSafari() {\r\n return !!(navigator.vendor && navigator.vendor.match(/apple/i));\r\n}\r\n\r\n","// Detect passive event listener support\r\nlet supportsPassive = false;\r\n/* eslint-disable */\r\ntry {\r\n window.addEventListener('test', null, Object.defineProperty({}, 'passive', {\r\n get: () => {\r\n supportsPassive = true;\r\n }\r\n }));\r\n} catch (e) {}\r\n/* eslint-enable */\r\n\r\n\r\n/**\r\n * @typedef {Object} PoolItem\r\n * @prop {HTMLElement | Window | Document} target\r\n * @prop {string} type\r\n * @prop {(e: any) => void} listener\r\n * @prop {boolean} passive\r\n */\r\n\r\nclass DOMEvents {\r\n constructor() {\r\n /**\r\n * @type {PoolItem[]}\r\n * @private\r\n */\r\n this._pool = [];\r\n }\r\n\r\n /**\r\n * Adds event listeners\r\n *\r\n * @param {HTMLElement | Window | Document} target\r\n * @param {string} type Can be multiple, separated by space.\r\n * @param {(e: any) => void} listener\r\n * @param {boolean=} passive\r\n */\r\n add(target, type, listener, passive) {\r\n this._toggleListener(target, type, listener, passive);\r\n }\r\n\r\n /**\r\n * Removes event listeners\r\n *\r\n * @param {HTMLElement | Window | Document} target\r\n * @param {string} type\r\n * @param {(e: any) => void} listener\r\n * @param {boolean=} passive\r\n */\r\n remove(target, type, listener, passive) {\r\n this._toggleListener(target, type, listener, passive, true);\r\n }\r\n\r\n /**\r\n * Removes all bound events\r\n */\r\n removeAll() {\r\n this._pool.forEach((poolItem) => {\r\n this._toggleListener(\r\n poolItem.target,\r\n poolItem.type,\r\n poolItem.listener,\r\n poolItem.passive,\r\n true,\r\n true\r\n );\r\n });\r\n this._pool = [];\r\n }\r\n\r\n /**\r\n * Adds or removes event\r\n *\r\n * @param {HTMLElement | Window | Document} target\r\n * @param {string} type\r\n * @param {(e: any) => void} listener\r\n * @param {boolean} passive\r\n * @param {boolean=} unbind Whether the event should be added or removed\r\n * @param {boolean=} skipPool Whether events pool should be skipped\r\n */\r\n _toggleListener(target, type, listener, passive, unbind, skipPool) {\r\n if (!target) {\r\n return;\r\n }\r\n\r\n const methodName = unbind ? 'removeEventListener' : 'addEventListener';\r\n const types = type.split(' ');\r\n types.forEach((eType) => {\r\n if (eType) {\r\n // Events pool is used to easily unbind all events when PhotoSwipe is closed,\r\n // so developer doesn't need to do this manually\r\n if (!skipPool) {\r\n if (unbind) {\r\n // Remove from the events pool\r\n this._pool = this._pool.filter((poolItem) => {\r\n return poolItem.type !== eType\r\n || poolItem.listener !== listener\r\n || poolItem.target !== target;\r\n });\r\n } else {\r\n // Add to the events pool\r\n this._pool.push({\r\n target,\r\n type: eType,\r\n listener,\r\n passive\r\n });\r\n }\r\n }\r\n\r\n\r\n // most PhotoSwipe events call preventDefault,\r\n // and we do not need browser to scroll the page\r\n const eventOptions = supportsPassive ? { passive: (passive || false) } : false;\r\n\r\n target[methodName](\r\n eType,\r\n listener,\r\n eventOptions\r\n );\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport default DOMEvents;\r\n","/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('../slide/slide.js').SlideData} SlideData */\r\n\r\n/**\r\n * @param {PhotoSwipeOptions} options\r\n * @param {PhotoSwipe} pswp\r\n */\r\nexport function getViewportSize(options, pswp) {\r\n if (options.getViewportSizeFn) {\r\n const newViewportSize = options.getViewportSizeFn(options, pswp);\r\n if (newViewportSize) {\r\n return newViewportSize;\r\n }\r\n }\r\n\r\n return {\r\n x: document.documentElement.clientWidth,\r\n\r\n // TODO: height on mobile is very incosistent due to toolbar\r\n // find a way to improve this\r\n //\r\n // document.documentElement.clientHeight - doesn't seem to work well\r\n y: window.innerHeight\r\n };\r\n}\r\n\r\n/**\r\n * Parses padding option.\r\n * Supported formats:\r\n *\r\n * // Object\r\n * padding: {\r\n * top: 0,\r\n * bottom: 0,\r\n * left: 0,\r\n * right: 0\r\n * }\r\n *\r\n * // A function that returns the object\r\n * paddingFn: (viewportSize, itemData, index) => {\r\n * return {\r\n * top: 0,\r\n * bottom: 0,\r\n * left: 0,\r\n * right: 0\r\n * };\r\n * }\r\n *\r\n * // Legacy variant\r\n * paddingLeft: 0,\r\n * paddingRight: 0,\r\n * paddingTop: 0,\r\n * paddingBottom: 0,\r\n *\r\n * @param {'left' | 'top' | 'bottom' | 'right'} prop\r\n * @param {PhotoSwipeOptions} options PhotoSwipe options\r\n * @param {{ x?: number; y?: number }} viewportSize PhotoSwipe viewport size, for example: { x:800, y:600 }\r\n * @param {SlideData} itemData Data about the slide\r\n * @param {number} index Slide index\r\n * @returns {number}\r\n */\r\nexport function parsePaddingOption(prop, options, viewportSize, itemData, index) {\r\n /** @type {number} */\r\n let paddingValue;\r\n\r\n if (options.paddingFn) {\r\n paddingValue = options.paddingFn(viewportSize, itemData, index)[prop];\r\n } else if (options.padding) {\r\n paddingValue = options.padding[prop];\r\n } else {\r\n const legacyPropName = 'padding' + prop[0].toUpperCase() + prop.slice(1);\r\n // @ts-expect-error\r\n if (options[legacyPropName]) {\r\n // @ts-expect-error\r\n paddingValue = options[legacyPropName];\r\n }\r\n }\r\n\r\n return paddingValue || 0;\r\n}\r\n\r\n/**\r\n * @param {PhotoSwipeOptions} options\r\n * @param {{ x?: number; y?: number }} viewportSize\r\n * @param {SlideData} itemData\r\n * @param {number} index\r\n */\r\nexport function getPanAreaSize(options, viewportSize, itemData, index) {\r\n return {\r\n x: viewportSize.x\r\n - parsePaddingOption('left', options, viewportSize, itemData, index)\r\n - parsePaddingOption('right', options, viewportSize, itemData, index),\r\n y: viewportSize.y\r\n - parsePaddingOption('top', options, viewportSize, itemData, index)\r\n - parsePaddingOption('bottom', options, viewportSize, itemData, index)\r\n };\r\n}\r\n","import {\r\n clamp\r\n} from '../util/util.js';\r\nimport { parsePaddingOption } from '../util/viewport-size.js';\r\n\r\n/** @typedef {import('./slide.js').default} Slide */\r\n/** @typedef {{ x?: number; y?: number }} Point */\r\n/** @typedef {'x' | 'y'} Axis */\r\n\r\n/**\r\n * Calculates minimum, maximum and initial (center) bounds of a slide\r\n */\r\nclass PanBounds {\r\n /**\r\n * @param {Slide} slide\r\n */\r\n constructor(slide) {\r\n this.slide = slide;\r\n\r\n this.currZoomLevel = 1;\r\n\r\n /** @type {Point} */\r\n this.center = {};\r\n /** @type {Point} */\r\n this.max = {};\r\n /** @type {Point} */\r\n this.min = {};\r\n\r\n this.reset();\r\n }\r\n\r\n /**\r\n * _getItemBounds\r\n *\r\n * @param {number} currZoomLevel\r\n */\r\n update(currZoomLevel) {\r\n this.currZoomLevel = currZoomLevel;\r\n\r\n if (!this.slide.width) {\r\n this.reset();\r\n } else {\r\n this._updateAxis('x');\r\n this._updateAxis('y');\r\n this.slide.pswp.dispatch('calcBounds', { slide: this.slide });\r\n }\r\n }\r\n\r\n /**\r\n * _calculateItemBoundsForAxis\r\n *\r\n * @param {Axis} axis\r\n */\r\n _updateAxis(axis) {\r\n const { pswp } = this.slide;\r\n const elSize = this.slide[axis === 'x' ? 'width' : 'height'] * this.currZoomLevel;\r\n const paddingProp = axis === 'x' ? 'left' : 'top';\r\n const padding = parsePaddingOption(\r\n paddingProp,\r\n pswp.options,\r\n pswp.viewportSize,\r\n this.slide.data,\r\n this.slide.index\r\n );\r\n\r\n const panAreaSize = this.slide.panAreaSize[axis];\r\n\r\n // Default position of element.\r\n // By defaul it is center of viewport:\r\n this.center[axis] = Math.round((panAreaSize - elSize) / 2) + padding;\r\n\r\n // maximum pan position\r\n this.max[axis] = (elSize > panAreaSize)\r\n ? Math.round(panAreaSize - elSize) + padding\r\n : this.center[axis];\r\n\r\n // minimum pan position\r\n this.min[axis] = (elSize > panAreaSize)\r\n ? padding\r\n : this.center[axis];\r\n }\r\n\r\n // _getZeroBounds\r\n reset() {\r\n this.center.x = 0;\r\n this.center.y = 0;\r\n this.max.x = 0;\r\n this.max.y = 0;\r\n this.min.x = 0;\r\n this.min.y = 0;\r\n }\r\n\r\n /**\r\n * Correct pan position if it's beyond the bounds\r\n *\r\n * @param {Axis} axis x or y\r\n * @param {number} panOffset\r\n */\r\n correctPan(axis, panOffset) { // checkPanBounds\r\n return clamp(panOffset, this.max[axis], this.min[axis]);\r\n }\r\n}\r\n\r\nexport default PanBounds;\r\n","const MAX_IMAGE_WIDTH = 4000;\r\n\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */\r\n/** @typedef {import('../slide/slide.js').SlideData} SlideData */\r\n\r\n/** @typedef {'fit' | 'fill' | number | ((zoomLevelObject: ZoomLevel) => number)} ZoomLevelOption */\r\n\r\n/**\r\n * Calculates zoom levels for specific slide.\r\n * Depends on viewport size and image size.\r\n */\r\nclass ZoomLevel {\r\n /**\r\n * @param {PhotoSwipeOptions} options PhotoSwipe options\r\n * @param {SlideData} itemData Slide data\r\n * @param {number} index Slide index\r\n * @param {PhotoSwipe=} pswp PhotoSwipe instance, can be undefined if not initialized yet\r\n */\r\n constructor(options, itemData, index, pswp) {\r\n this.pswp = pswp;\r\n this.options = options;\r\n this.itemData = itemData;\r\n this.index = index;\r\n }\r\n\r\n /**\r\n * Calculate initial, secondary and maximum zoom level for the specified slide.\r\n *\r\n * It should be called when either image or viewport size changes.\r\n *\r\n * @param {number} maxWidth\r\n * @param {number} maxHeight\r\n * @param {{ x?: number; y?: number }} panAreaSize\r\n */\r\n update(maxWidth, maxHeight, panAreaSize) {\r\n this.elementSize = {\r\n x: maxWidth,\r\n y: maxHeight\r\n };\r\n\r\n this.panAreaSize = panAreaSize;\r\n\r\n const hRatio = this.panAreaSize.x / this.elementSize.x;\r\n const vRatio = this.panAreaSize.y / this.elementSize.y;\r\n\r\n this.fit = Math.min(1, hRatio < vRatio ? hRatio : vRatio);\r\n this.fill = Math.min(1, hRatio > vRatio ? hRatio : vRatio);\r\n\r\n // zoom.vFill defines zoom level of the image\r\n // when it has 100% of viewport vertical space (height)\r\n this.vFill = Math.min(1, vRatio);\r\n\r\n this.initial = this._getInitial();\r\n this.secondary = this._getSecondary();\r\n this.max = Math.max(\r\n this.initial,\r\n this.secondary,\r\n this._getMax()\r\n );\r\n\r\n this.min = Math.min(\r\n this.fit,\r\n this.initial,\r\n this.secondary\r\n );\r\n\r\n if (this.pswp) {\r\n this.pswp.dispatch('zoomLevelsUpdate', { zoomLevels: this, slideData: this.itemData });\r\n }\r\n }\r\n\r\n /**\r\n * Parses user-defined zoom option.\r\n *\r\n * @private\r\n * @param {'initial' | 'secondary' | 'max'} optionPrefix Zoom level option prefix (initial, secondary, max)\r\n */\r\n _parseZoomLevelOption(optionPrefix) {\r\n // eslint-disable-next-line max-len\r\n const optionName = /** @type {'initialZoomLevel' | 'secondaryZoomLevel' | 'maxZoomLevel'} */ (optionPrefix + 'ZoomLevel');\r\n const optionValue = this.options[optionName];\r\n\r\n if (!optionValue) {\r\n return;\r\n }\r\n\r\n if (typeof optionValue === 'function') {\r\n return optionValue(this);\r\n }\r\n\r\n if (optionValue === 'fill') {\r\n return this.fill;\r\n }\r\n\r\n if (optionValue === 'fit') {\r\n return this.fit;\r\n }\r\n\r\n return Number(optionValue);\r\n }\r\n\r\n /**\r\n * Get zoom level to which image will be zoomed after double-tap gesture,\r\n * or when user clicks on zoom icon,\r\n * or mouse-click on image itself.\r\n * If you return 1 image will be zoomed to its original size.\r\n *\r\n * @private\r\n * @return {number}\r\n */\r\n _getSecondary() {\r\n let currZoomLevel = this._parseZoomLevelOption('secondary');\r\n\r\n if (currZoomLevel) {\r\n return currZoomLevel;\r\n }\r\n\r\n // 3x of \"fit\" state, but not larger than original\r\n currZoomLevel = Math.min(1, this.fit * 3);\r\n\r\n if (currZoomLevel * this.elementSize.x > MAX_IMAGE_WIDTH) {\r\n currZoomLevel = MAX_IMAGE_WIDTH / this.elementSize.x;\r\n }\r\n\r\n return currZoomLevel;\r\n }\r\n\r\n /**\r\n * Get initial image zoom level.\r\n *\r\n * @private\r\n * @return {number}\r\n */\r\n _getInitial() {\r\n return this._parseZoomLevelOption('initial') || this.fit;\r\n }\r\n\r\n /**\r\n * Maximum zoom level when user zooms\r\n * via zoom/pinch gesture,\r\n * via cmd/ctrl-wheel or via trackpad.\r\n *\r\n * @private\r\n * @return {number}\r\n */\r\n _getMax() {\r\n const currZoomLevel = this._parseZoomLevelOption('max');\r\n\r\n if (currZoomLevel) {\r\n return currZoomLevel;\r\n }\r\n\r\n // max zoom level is x4 from \"fit state\",\r\n // used for zoom gesture and ctrl/trackpad zoom\r\n return Math.max(1, this.fit * 4);\r\n }\r\n}\r\n\r\nexport default ZoomLevel;\r\n","/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('../photoswipe.js').Point} Point */\r\n\r\n/**\r\n * @typedef {_SlideData & Record} SlideData\r\n * @typedef {Object} _SlideData\r\n * @prop {HTMLElement=} element thumbnail element\r\n * @prop {string=} src image URL\r\n * @prop {string=} srcset image srcset\r\n * @prop {number=} w image width (deprecated)\r\n * @prop {number=} h image height (deprecated)\r\n * @prop {number=} width image width\r\n * @prop {number=} height image height\r\n * @prop {string=} msrc placeholder image URL that's displayed before large image is loaded\r\n * @prop {string=} alt image alt text\r\n * @prop {boolean=} thumbCropped whether thumbnail is cropped client-side or not\r\n * @prop {string=} html html content of a slide\r\n * @prop {'image' | 'html' | string} [type] slide type\r\n */\r\n\r\nimport {\r\n createElement,\r\n setTransform,\r\n equalizePoints,\r\n roundPoint,\r\n toTransformString,\r\n clamp,\r\n} from '../util/util.js';\r\n\r\nimport PanBounds from './pan-bounds.js';\r\nimport ZoomLevel from './zoom-level.js';\r\nimport { getPanAreaSize } from '../util/viewport-size.js';\r\n\r\n/**\r\n * Renders and allows to control a single slide\r\n */\r\nclass Slide {\r\n /**\r\n * @param {SlideData} data\r\n * @param {number} index\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(data, index, pswp) {\r\n this.data = data;\r\n this.index = index;\r\n this.pswp = pswp;\r\n this.isActive = (index === pswp.currIndex);\r\n this.currentResolution = 0;\r\n /** @type {Point} */\r\n this.panAreaSize = {};\r\n\r\n this.isFirstSlide = (this.isActive && !pswp.opener.isOpen);\r\n\r\n this.zoomLevels = new ZoomLevel(pswp.options, data, index, pswp);\r\n\r\n this.pswp.dispatch('gettingData', {\r\n slide: this,\r\n data: this.data,\r\n index\r\n });\r\n\r\n this.pan = {\r\n x: 0,\r\n y: 0\r\n };\r\n\r\n this.content = this.pswp.contentLoader.getContentBySlide(this);\r\n this.container = createElement('pswp__zoom-wrap');\r\n\r\n this.currZoomLevel = 1;\r\n /** @type {number} */\r\n this.width = this.content.width;\r\n /** @type {number} */\r\n this.height = this.content.height;\r\n\r\n this.bounds = new PanBounds(this);\r\n\r\n this.prevDisplayedWidth = -1;\r\n this.prevDisplayedHeight = -1;\r\n\r\n this.pswp.dispatch('slideInit', { slide: this });\r\n }\r\n\r\n /**\r\n * If this slide is active/current/visible\r\n *\r\n * @param {boolean} isActive\r\n */\r\n setIsActive(isActive) {\r\n if (isActive && !this.isActive) {\r\n // slide just became active\r\n this.activate();\r\n } else if (!isActive && this.isActive) {\r\n // slide just became non-active\r\n this.deactivate();\r\n }\r\n }\r\n\r\n /**\r\n * Appends slide content to DOM\r\n *\r\n * @param {HTMLElement} holderElement\r\n */\r\n append(holderElement) {\r\n this.holderElement = holderElement;\r\n\r\n this.container.style.transformOrigin = '0 0';\r\n\r\n // Slide appended to DOM\r\n if (!this.data) {\r\n return;\r\n }\r\n\r\n this.calculateSize();\r\n\r\n this.load();\r\n this.updateContentSize();\r\n this.appendHeavy();\r\n\r\n this.holderElement.appendChild(this.container);\r\n\r\n this.zoomAndPanToInitial();\r\n\r\n this.pswp.dispatch('firstZoomPan', { slide: this });\r\n\r\n this.applyCurrentZoomPan();\r\n\r\n this.pswp.dispatch('afterSetContent', { slide: this });\r\n\r\n if (this.isActive) {\r\n this.activate();\r\n }\r\n }\r\n\r\n load() {\r\n this.content.load();\r\n this.pswp.dispatch('slideLoad', { slide: this });\r\n }\r\n\r\n /**\r\n * Append \"heavy\" DOM elements\r\n *\r\n * This may depend on a type of slide,\r\n * but generally these are large images.\r\n */\r\n appendHeavy() {\r\n const { pswp } = this;\r\n const appendHeavyNearby = true; // todo\r\n\r\n // Avoid appending heavy elements during animations\r\n if (this.heavyAppended\r\n || !pswp.opener.isOpen\r\n || pswp.mainScroll.isShifted()\r\n || (!this.isActive && !appendHeavyNearby)) {\r\n return;\r\n }\r\n\r\n if (this.pswp.dispatch('appendHeavy', { slide: this }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n this.heavyAppended = true;\r\n\r\n this.content.append();\r\n\r\n this.pswp.dispatch('appendHeavyContent', { slide: this });\r\n }\r\n\r\n /**\r\n * Triggered when this slide is active (selected).\r\n *\r\n * If it's part of opening/closing transition -\r\n * activate() will trigger after the transition is ended.\r\n */\r\n activate() {\r\n this.isActive = true;\r\n this.appendHeavy();\r\n this.content.activate();\r\n this.pswp.dispatch('slideActivate', { slide: this });\r\n }\r\n\r\n /**\r\n * Triggered when this slide becomes inactive.\r\n *\r\n * Slide can become inactive only after it was active.\r\n */\r\n deactivate() {\r\n this.isActive = false;\r\n this.content.deactivate();\r\n\r\n if (this.currZoomLevel !== this.zoomLevels.initial) {\r\n // allow filtering\r\n this.calculateSize();\r\n }\r\n\r\n // reset zoom level\r\n this.currentResolution = 0;\r\n this.zoomAndPanToInitial();\r\n this.applyCurrentZoomPan();\r\n this.updateContentSize();\r\n\r\n this.pswp.dispatch('slideDeactivate', { slide: this });\r\n }\r\n\r\n /**\r\n * The slide should destroy itself, it will never be used again.\r\n * (unbind all events and destroy internal components)\r\n */\r\n destroy() {\r\n this.content.hasSlide = false;\r\n this.content.remove();\r\n this.container.remove();\r\n this.pswp.dispatch('slideDestroy', { slide: this });\r\n }\r\n\r\n resize() {\r\n if (this.currZoomLevel === this.zoomLevels.initial || !this.isActive) {\r\n // Keep initial zoom level if it was before the resize,\r\n // as well as when this slide is not active\r\n\r\n // Reset position and scale to original state\r\n this.calculateSize();\r\n this.currentResolution = 0;\r\n this.zoomAndPanToInitial();\r\n this.applyCurrentZoomPan();\r\n this.updateContentSize();\r\n } else {\r\n // readjust pan position if it's beyond the bounds\r\n this.calculateSize();\r\n this.bounds.update(this.currZoomLevel);\r\n this.panTo(this.pan.x, this.pan.y);\r\n }\r\n }\r\n\r\n\r\n /**\r\n * Apply size to current slide content,\r\n * based on the current resolution and scale.\r\n *\r\n * @param {boolean=} force if size should be updated even if dimensions weren't changed\r\n */\r\n updateContentSize(force) {\r\n // Use initial zoom level\r\n // if resolution is not defined (user didn't zoom yet)\r\n const scaleMultiplier = this.currentResolution || this.zoomLevels.initial;\r\n\r\n if (!scaleMultiplier) {\r\n return;\r\n }\r\n\r\n const width = Math.round(this.width * scaleMultiplier) || this.pswp.viewportSize.x;\r\n const height = Math.round(this.height * scaleMultiplier) || this.pswp.viewportSize.y;\r\n\r\n if (!this.sizeChanged(width, height) && !force) {\r\n return;\r\n }\r\n this.content.setDisplayedSize(width, height);\r\n }\r\n\r\n /**\r\n * @param {number} width\r\n * @param {number} height\r\n */\r\n sizeChanged(width, height) {\r\n if (width !== this.prevDisplayedWidth\r\n || height !== this.prevDisplayedHeight) {\r\n this.prevDisplayedWidth = width;\r\n this.prevDisplayedHeight = height;\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n getPlaceholderElement() {\r\n if (this.content.placeholder) {\r\n return this.content.placeholder.element;\r\n }\r\n }\r\n\r\n /**\r\n * Zoom current slide image to...\r\n *\r\n * @param {number} destZoomLevel Destination zoom level.\r\n * @param {{ x?: number; y?: number }} centerPoint\r\n * Transform origin center point, or false if viewport center should be used.\r\n * @param {number | false} [transitionDuration] Transition duration, may be set to 0.\r\n * @param {boolean=} ignoreBounds Minimum and maximum zoom levels will be ignored.\r\n * @return {boolean=} Returns true if animated.\r\n */\r\n zoomTo(destZoomLevel, centerPoint, transitionDuration, ignoreBounds) {\r\n const { pswp } = this;\r\n if (!this.isZoomable()\r\n || pswp.mainScroll.isShifted()) {\r\n return;\r\n }\r\n\r\n pswp.dispatch('beforeZoomTo', {\r\n destZoomLevel, centerPoint, transitionDuration\r\n });\r\n\r\n // stop all pan and zoom transitions\r\n pswp.animations.stopAllPan();\r\n\r\n // if (!centerPoint) {\r\n // centerPoint = pswp.getViewportCenterPoint();\r\n // }\r\n\r\n const prevZoomLevel = this.currZoomLevel;\r\n\r\n if (!ignoreBounds) {\r\n destZoomLevel = clamp(destZoomLevel, this.zoomLevels.min, this.zoomLevels.max);\r\n }\r\n\r\n // if (transitionDuration === undefined) {\r\n // transitionDuration = this.pswp.options.zoomAnimationDuration;\r\n // }\r\n\r\n this.setZoomLevel(destZoomLevel);\r\n this.pan.x = this.calculateZoomToPanOffset('x', centerPoint, prevZoomLevel);\r\n this.pan.y = this.calculateZoomToPanOffset('y', centerPoint, prevZoomLevel);\r\n roundPoint(this.pan);\r\n\r\n const finishTransition = () => {\r\n this._setResolution(destZoomLevel);\r\n this.applyCurrentZoomPan();\r\n };\r\n\r\n if (!transitionDuration) {\r\n finishTransition();\r\n } else {\r\n pswp.animations.startTransition({\r\n isPan: true,\r\n name: 'zoomTo',\r\n target: this.container,\r\n transform: this.getCurrentTransform(),\r\n onComplete: finishTransition,\r\n duration: transitionDuration,\r\n easing: pswp.options.easing\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * @param {{ x?: number, y?: number }} [centerPoint]\r\n */\r\n toggleZoom(centerPoint) {\r\n this.zoomTo(\r\n this.currZoomLevel === this.zoomLevels.initial\r\n ? this.zoomLevels.secondary : this.zoomLevels.initial,\r\n centerPoint,\r\n this.pswp.options.zoomAnimationDuration\r\n );\r\n }\r\n\r\n /**\r\n * Updates zoom level property and recalculates new pan bounds,\r\n * unlike zoomTo it does not apply transform (use applyCurrentZoomPan)\r\n *\r\n * @param {number} currZoomLevel\r\n */\r\n setZoomLevel(currZoomLevel) {\r\n this.currZoomLevel = currZoomLevel;\r\n this.bounds.update(this.currZoomLevel);\r\n }\r\n\r\n /**\r\n * Get pan position after zoom at a given `point`.\r\n *\r\n * Always call setZoomLevel(newZoomLevel) beforehand to recalculate\r\n * pan bounds according to the new zoom level.\r\n *\r\n * @param {'x' | 'y'} axis\r\n * @param {{ x?: number; y?: number }} [point]\r\n * point based on which zoom is performed, usually refers to the current mouse position,\r\n * if false - viewport center will be used.\r\n * @param {number=} prevZoomLevel Zoom level before new zoom was applied.\r\n */\r\n calculateZoomToPanOffset(axis, point, prevZoomLevel) {\r\n const totalPanDistance = this.bounds.max[axis] - this.bounds.min[axis];\r\n if (totalPanDistance === 0) {\r\n return this.bounds.center[axis];\r\n }\r\n\r\n if (!point) {\r\n point = this.pswp.getViewportCenterPoint();\r\n }\r\n\r\n const zoomFactor = this.currZoomLevel / prevZoomLevel;\r\n return this.bounds.correctPan(\r\n axis,\r\n (this.pan[axis] - point[axis]) * zoomFactor + point[axis]\r\n );\r\n }\r\n\r\n /**\r\n * Apply pan and keep it within bounds.\r\n *\r\n * @param {number} panX\r\n * @param {number} panY\r\n */\r\n panTo(panX, panY) {\r\n this.pan.x = this.bounds.correctPan('x', panX);\r\n this.pan.y = this.bounds.correctPan('y', panY);\r\n this.applyCurrentZoomPan();\r\n }\r\n\r\n /**\r\n * If the slide in the current state can be panned by the user\r\n */\r\n isPannable() {\r\n return this.width && (this.currZoomLevel > this.zoomLevels.fit);\r\n }\r\n\r\n /**\r\n * If the slide can be zoomed\r\n */\r\n isZoomable() {\r\n return this.width && this.content.isZoomable();\r\n }\r\n\r\n /**\r\n * Apply transform and scale based on\r\n * the current pan position (this.pan) and zoom level (this.currZoomLevel)\r\n */\r\n applyCurrentZoomPan() {\r\n this._applyZoomTransform(this.pan.x, this.pan.y, this.currZoomLevel);\r\n if (this === this.pswp.currSlide) {\r\n this.pswp.dispatch('zoomPanUpdate', { slide: this });\r\n }\r\n }\r\n\r\n zoomAndPanToInitial() {\r\n this.currZoomLevel = this.zoomLevels.initial;\r\n\r\n // pan according to the zoom level\r\n this.bounds.update(this.currZoomLevel);\r\n equalizePoints(this.pan, this.bounds.center);\r\n this.pswp.dispatch('initialZoomPan', { slide: this });\r\n }\r\n\r\n /**\r\n * Set translate and scale based on current resolution\r\n *\r\n * @param {number} x\r\n * @param {number} y\r\n * @param {number} zoom\r\n */\r\n _applyZoomTransform(x, y, zoom) {\r\n zoom /= this.currentResolution || this.zoomLevels.initial;\r\n setTransform(this.container, x, y, zoom);\r\n }\r\n\r\n calculateSize() {\r\n const { pswp } = this;\r\n\r\n equalizePoints(\r\n this.panAreaSize,\r\n getPanAreaSize(pswp.options, pswp.viewportSize, this.data, this.index)\r\n );\r\n\r\n this.zoomLevels.update(this.width, this.height, this.panAreaSize);\r\n\r\n pswp.dispatch('calcSlideSize', {\r\n slide: this\r\n });\r\n }\r\n\r\n getCurrentTransform() {\r\n const scale = this.currZoomLevel / (this.currentResolution || this.zoomLevels.initial);\r\n return toTransformString(this.pan.x, this.pan.y, scale);\r\n }\r\n\r\n /**\r\n * Set resolution and re-render the image.\r\n *\r\n * For example, if the real image size is 2000x1500,\r\n * and resolution is 0.5 - it will be rendered as 1000x750.\r\n *\r\n * Image with zoom level 2 and resolution 0.5 is\r\n * the same as image with zoom level 1 and resolution 1.\r\n *\r\n * Used to optimize animations and make\r\n * sure that browser renders image in highest quality.\r\n * Also used by responsive images to load the correct one.\r\n *\r\n * @param {number} newResolution\r\n */\r\n _setResolution(newResolution) {\r\n if (newResolution === this.currentResolution) {\r\n return;\r\n }\r\n\r\n this.currentResolution = newResolution;\r\n this.updateContentSize();\r\n\r\n this.pswp.dispatch('resolutionChanged');\r\n }\r\n}\r\n\r\nexport default Slide;\r\n","import {\r\n equalizePoints, roundPoint, clamp\r\n} from '../util/util.js';\r\n\r\n/** @typedef {import('../photoswipe.js').Point} Point */\r\n/** @typedef {import('./gestures.js').default} Gestures */\r\n\r\nconst PAN_END_FRICTION = 0.35;\r\nconst VERTICAL_DRAG_FRICTION = 0.6;\r\n\r\n// 1 corresponds to the third of viewport height\r\nconst MIN_RATIO_TO_CLOSE = 0.4;\r\n\r\n// Minimum speed required to navigate\r\n// to next or previous slide\r\nconst MIN_NEXT_SLIDE_SPEED = 0.5;\r\n\r\n/**\r\n * @param {number} initialVelocity\r\n * @param {number} decelerationRate\r\n */\r\nfunction project(initialVelocity, decelerationRate) {\r\n return initialVelocity * decelerationRate / (1 - decelerationRate);\r\n}\r\n\r\n/**\r\n * Handles single pointer dragging\r\n */\r\nclass DragHandler {\r\n /**\r\n * @param {Gestures} gestures\r\n */\r\n constructor(gestures) {\r\n this.gestures = gestures;\r\n this.pswp = gestures.pswp;\r\n /** @type {Point} */\r\n this.startPan = {};\r\n }\r\n\r\n start() {\r\n equalizePoints(this.startPan, this.pswp.currSlide.pan);\r\n this.pswp.animations.stopAll();\r\n }\r\n\r\n change() {\r\n const { p1, prevP1, dragAxis, pswp } = this.gestures;\r\n const { currSlide } = pswp;\r\n\r\n if (dragAxis === 'y'\r\n && pswp.options.closeOnVerticalDrag\r\n && currSlide.currZoomLevel <= currSlide.zoomLevels.fit\r\n && !this.gestures.isMultitouch) {\r\n // Handle vertical drag to close\r\n const panY = currSlide.pan.y + (p1.y - prevP1.y);\r\n if (!pswp.dispatch('verticalDrag', { panY }).defaultPrevented) {\r\n this._setPanWithFriction('y', panY, VERTICAL_DRAG_FRICTION);\r\n const bgOpacity = 1 - Math.abs(this._getVerticalDragRatio(currSlide.pan.y));\r\n pswp.applyBgOpacity(bgOpacity);\r\n currSlide.applyCurrentZoomPan();\r\n }\r\n } else {\r\n const mainScrollChanged = this._panOrMoveMainScroll('x');\r\n if (!mainScrollChanged) {\r\n this._panOrMoveMainScroll('y');\r\n\r\n roundPoint(currSlide.pan);\r\n currSlide.applyCurrentZoomPan();\r\n }\r\n }\r\n }\r\n\r\n end() {\r\n const { pswp, velocity } = this.gestures;\r\n const { mainScroll } = pswp;\r\n let indexDiff = 0;\r\n\r\n pswp.animations.stopAll();\r\n\r\n // Handle main scroll if it's shifted\r\n if (mainScroll.isShifted()) {\r\n // Position of the main scroll relative to the viewport\r\n const mainScrollShiftDiff = mainScroll.x - mainScroll.getCurrSlideX();\r\n\r\n // Ratio between 0 and 1:\r\n // 0 - slide is not visible at all,\r\n // 0.5 - half of the slide is vicible\r\n // 1 - slide is fully visible\r\n const currentSlideVisibilityRatio = (mainScrollShiftDiff / pswp.viewportSize.x);\r\n\r\n // Go next slide.\r\n //\r\n // - if velocity and its direction is matched\r\n // and we see at least tiny part of the next slide\r\n //\r\n // - or if we see less than 50% of the current slide\r\n // and velocity is close to 0\r\n //\r\n if ((velocity.x < -MIN_NEXT_SLIDE_SPEED && currentSlideVisibilityRatio < 0)\r\n || (velocity.x < 0.1 && currentSlideVisibilityRatio < -0.5)) {\r\n // Go to next slide\r\n indexDiff = 1;\r\n velocity.x = Math.min(velocity.x, 0);\r\n } else if ((velocity.x > MIN_NEXT_SLIDE_SPEED && currentSlideVisibilityRatio > 0)\r\n || (velocity.x > -0.1 && currentSlideVisibilityRatio > 0.5)) {\r\n // Go to prev slide\r\n indexDiff = -1;\r\n velocity.x = Math.max(velocity.x, 0);\r\n }\r\n\r\n mainScroll.moveIndexBy(indexDiff, true, velocity.x);\r\n }\r\n\r\n // Restore zoom level\r\n if (pswp.currSlide.currZoomLevel > pswp.currSlide.zoomLevels.max\r\n || this.gestures.isMultitouch) {\r\n this.gestures.zoomLevels.correctZoomPan(true);\r\n } else {\r\n // we run two animations instead of one,\r\n // as each axis has own pan boundaries and thus different spring function\r\n // (correctZoomPan does not have this functionality,\r\n // it animates all properties with single timing function)\r\n this._finishPanGestureForAxis('x');\r\n this._finishPanGestureForAxis('y');\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {'x' | 'y'} axis\r\n */\r\n _finishPanGestureForAxis(axis) {\r\n const { pswp } = this;\r\n const { currSlide } = pswp;\r\n const { velocity } = this.gestures;\r\n const { pan, bounds } = currSlide;\r\n const panPos = pan[axis];\r\n const restoreBgOpacity = (pswp.bgOpacity < 1 && axis === 'y');\r\n\r\n // 0.995 means - scroll view loses 0.5% of its velocity per millisecond\r\n // Inceasing this number will reduce travel distance\r\n const decelerationRate = 0.995; // 0.99\r\n\r\n // Pan position if there is no bounds\r\n const projectedPosition = panPos + project(velocity[axis], decelerationRate);\r\n\r\n if (restoreBgOpacity) {\r\n const vDragRatio = this._getVerticalDragRatio(panPos);\r\n const projectedVDragRatio = this._getVerticalDragRatio(projectedPosition);\r\n\r\n // If we are above and moving upwards,\r\n // or if we are below and moving downwards\r\n if ((vDragRatio < 0 && projectedVDragRatio < -MIN_RATIO_TO_CLOSE)\r\n || (vDragRatio > 0 && projectedVDragRatio > MIN_RATIO_TO_CLOSE)) {\r\n pswp.close();\r\n return;\r\n }\r\n }\r\n\r\n // Pan position with corrected bounds\r\n const correctedPanPosition = bounds.correctPan(axis, projectedPosition);\r\n\r\n // Exit if pan position should not be changed\r\n // or if speed it too low\r\n if (panPos === correctedPanPosition) {\r\n return;\r\n }\r\n\r\n // Overshoot if the final position is out of pan bounds\r\n const dampingRatio = (correctedPanPosition === projectedPosition) ? 1 : 0.82;\r\n\r\n const initialBgOpacity = pswp.bgOpacity;\r\n const totalPanDist = correctedPanPosition - panPos;\r\n\r\n pswp.animations.startSpring({\r\n name: 'panGesture' + axis,\r\n isPan: true,\r\n start: panPos,\r\n end: correctedPanPosition,\r\n velocity: velocity[axis],\r\n dampingRatio,\r\n onUpdate: (pos) => {\r\n // Animate opacity of background relative to Y pan position of an image\r\n if (restoreBgOpacity && pswp.bgOpacity < 1) {\r\n // 0 - start of animation, 1 - end of animation\r\n const animationProgressRatio = 1 - (correctedPanPosition - pos) / totalPanDist;\r\n\r\n // We clamp opacity to keep it between 0 and 1.\r\n // As progress ratio can be larger than 1 due to overshoot,\r\n // and we do not want to bounce opacity.\r\n pswp.applyBgOpacity(clamp(\r\n initialBgOpacity + (1 - initialBgOpacity) * animationProgressRatio,\r\n 0,\r\n 1\r\n ));\r\n }\r\n\r\n pan[axis] = Math.floor(pos);\r\n currSlide.applyCurrentZoomPan();\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Update position of the main scroll,\r\n * or/and update pan position of the current slide.\r\n *\r\n * Should return true if it changes (or can change) main scroll.\r\n *\r\n * @private\r\n * @param {'x' | 'y'} axis\r\n */\r\n _panOrMoveMainScroll(axis) {\r\n const { p1, pswp, dragAxis, prevP1, isMultitouch } = this.gestures;\r\n const { currSlide, mainScroll } = pswp;\r\n const delta = (p1[axis] - prevP1[axis]);\r\n const newMainScrollX = mainScroll.x + delta;\r\n\r\n if (!delta) {\r\n return;\r\n }\r\n\r\n // Always move main scroll if image can not be panned\r\n if (axis === 'x' && !currSlide.isPannable() && !isMultitouch) {\r\n mainScroll.moveTo(newMainScrollX, true);\r\n return true; // changed main scroll\r\n }\r\n\r\n const { bounds } = currSlide;\r\n const newPan = currSlide.pan[axis] + delta;\r\n\r\n if (pswp.options.allowPanToNext\r\n && dragAxis === 'x'\r\n && axis === 'x'\r\n && !isMultitouch) {\r\n const currSlideMainScrollX = mainScroll.getCurrSlideX();\r\n\r\n // Position of the main scroll relative to the viewport\r\n const mainScrollShiftDiff = mainScroll.x - currSlideMainScrollX;\r\n\r\n const isLeftToRight = delta > 0;\r\n const isRightToLeft = !isLeftToRight;\r\n\r\n if (newPan > bounds.min[axis] && isLeftToRight) {\r\n // Panning from left to right, beyond the left edge\r\n\r\n // Wether the image was at minimum pan position (or less)\r\n // when this drag gesture started.\r\n // Minimum pan position refers to the left edge of the image.\r\n const wasAtMinPanPosition = (bounds.min[axis] <= this.startPan[axis]);\r\n\r\n if (wasAtMinPanPosition) {\r\n mainScroll.moveTo(newMainScrollX, true);\r\n return true;\r\n } else {\r\n this._setPanWithFriction(axis, newPan);\r\n //currSlide.pan[axis] = newPan;\r\n }\r\n } else if (newPan < bounds.max[axis] && isRightToLeft) {\r\n // Paning from right to left, beyond the right edge\r\n\r\n // Maximum pan position refers to the right edge of the image.\r\n const wasAtMaxPanPosition = (this.startPan[axis] <= bounds.max[axis]);\r\n\r\n if (wasAtMaxPanPosition) {\r\n mainScroll.moveTo(newMainScrollX, true);\r\n return true;\r\n } else {\r\n this._setPanWithFriction(axis, newPan);\r\n //currSlide.pan[axis] = newPan;\r\n }\r\n } else {\r\n // If main scroll is shifted\r\n if (mainScrollShiftDiff !== 0) {\r\n // If main scroll is shifted right\r\n if (mainScrollShiftDiff > 0 /*&& isRightToLeft*/) {\r\n mainScroll.moveTo(Math.max(newMainScrollX, currSlideMainScrollX), true);\r\n return true;\r\n } else if (mainScrollShiftDiff < 0 /*&& isLeftToRight*/) {\r\n // Main scroll is shifted left (Position is less than 0 comparing to the viewport 0)\r\n mainScroll.moveTo(Math.min(newMainScrollX, currSlideMainScrollX), true);\r\n return true;\r\n }\r\n } else {\r\n // We are within pan bounds, so just pan\r\n this._setPanWithFriction(axis, newPan);\r\n }\r\n }\r\n } else {\r\n if (axis === 'y') {\r\n // Do not pan vertically if main scroll is shifted o\r\n if (!mainScroll.isShifted() && bounds.min.y !== bounds.max.y) {\r\n this._setPanWithFriction(axis, newPan);\r\n }\r\n } else {\r\n this._setPanWithFriction(axis, newPan);\r\n }\r\n }\r\n }\r\n //\r\n // If we move above - the ratio is negative\r\n // If we move below the ratio is positive\r\n\r\n /**\r\n * Relation between pan Y position and third of viewport height.\r\n *\r\n * When we are at initial position (center bounds) - the ratio is 0,\r\n * if position is shifted upwards - the ratio is negative,\r\n * if position is shifted downwards - the ratio is positive.\r\n *\r\n * @private\r\n * @param {number} panY The current pan Y position.\r\n */\r\n _getVerticalDragRatio(panY) {\r\n return (panY - this.pswp.currSlide.bounds.center.y)\r\n / (this.pswp.viewportSize.y / 3);\r\n }\r\n\r\n /**\r\n * Set pan position of the current slide.\r\n * Apply friction if the position is beyond the pan bounds,\r\n * or if custom friction is defined.\r\n *\r\n * @private\r\n * @param {'x' | 'y'} axis\r\n * @param {number} potentialPan\r\n * @param {number=} customFriction (0.1 - 1)\r\n */\r\n _setPanWithFriction(axis, potentialPan, customFriction) {\r\n const { pan, bounds } = this.pswp.currSlide;\r\n const correctedPan = bounds.correctPan(axis, potentialPan);\r\n // If we are out of pan bounds\r\n if (correctedPan !== potentialPan || customFriction) {\r\n const delta = Math.round(potentialPan - pan[axis]);\r\n pan[axis] += delta * (customFriction || PAN_END_FRICTION);\r\n } else {\r\n pan[axis] = potentialPan;\r\n }\r\n }\r\n}\r\n\r\nexport default DragHandler;\r\n","import {\r\n equalizePoints, getDistanceBetween, clamp, pointsEqual\r\n} from '../util/util.js';\r\n\r\n/** @typedef {import('../photoswipe.js').Point} Point */\r\n/** @typedef {import('./gestures.js').default} Gestures */\r\n\r\nconst UPPER_ZOOM_FRICTION = 0.05;\r\nconst LOWER_ZOOM_FRICTION = 0.15;\r\n\r\n\r\n/**\r\n * Get center point between two points\r\n *\r\n * @param {Point} p\r\n * @param {Point} p1\r\n * @param {Point} p2\r\n */\r\nfunction getZoomPointsCenter(p, p1, p2) {\r\n p.x = (p1.x + p2.x) / 2;\r\n p.y = (p1.y + p2.y) / 2;\r\n return p;\r\n}\r\n\r\nclass ZoomHandler {\r\n /**\r\n * @param {Gestures} gestures\r\n */\r\n constructor(gestures) {\r\n this.gestures = gestures;\r\n this.pswp = this.gestures.pswp;\r\n /** @type {Point} */\r\n this._startPan = {};\r\n\r\n /** @type {Point} */\r\n this._startZoomPoint = {};\r\n /** @type {Point} */\r\n this._zoomPoint = {};\r\n }\r\n\r\n start() {\r\n this._startZoomLevel = this.pswp.currSlide.currZoomLevel;\r\n equalizePoints(this._startPan, this.pswp.currSlide.pan);\r\n this.pswp.animations.stopAllPan();\r\n this._wasOverFitZoomLevel = false;\r\n }\r\n\r\n change() {\r\n const { p1, startP1, p2, startP2, pswp } = this.gestures;\r\n const { currSlide } = pswp;\r\n const minZoomLevel = currSlide.zoomLevels.min;\r\n const maxZoomLevel = currSlide.zoomLevels.max;\r\n\r\n if (!currSlide.isZoomable() || pswp.mainScroll.isShifted()) {\r\n return;\r\n }\r\n\r\n getZoomPointsCenter(this._startZoomPoint, startP1, startP2);\r\n getZoomPointsCenter(this._zoomPoint, p1, p2);\r\n\r\n let currZoomLevel = (1 / getDistanceBetween(startP1, startP2))\r\n * getDistanceBetween(p1, p2)\r\n * this._startZoomLevel;\r\n\r\n // slightly over the zoom.fit\r\n if (currZoomLevel > currSlide.zoomLevels.initial + (currSlide.zoomLevels.initial / 15)) {\r\n this._wasOverFitZoomLevel = true;\r\n }\r\n\r\n if (currZoomLevel < minZoomLevel) {\r\n if (pswp.options.pinchToClose\r\n && !this._wasOverFitZoomLevel\r\n && this._startZoomLevel <= currSlide.zoomLevels.initial) {\r\n // fade out background if zooming out\r\n const bgOpacity = 1 - ((minZoomLevel - currZoomLevel) / (minZoomLevel / 1.2));\r\n if (!pswp.dispatch('pinchClose', { bgOpacity }).defaultPrevented) {\r\n pswp.applyBgOpacity(bgOpacity);\r\n }\r\n } else {\r\n // Apply the friction if zoom level is below the min\r\n currZoomLevel = minZoomLevel - (minZoomLevel - currZoomLevel) * LOWER_ZOOM_FRICTION;\r\n }\r\n } else if (currZoomLevel > maxZoomLevel) {\r\n // Apply the friction if zoom level is above the max\r\n currZoomLevel = maxZoomLevel + (currZoomLevel - maxZoomLevel) * UPPER_ZOOM_FRICTION;\r\n }\r\n\r\n currSlide.pan.x = this._calculatePanForZoomLevel('x', currZoomLevel);\r\n currSlide.pan.y = this._calculatePanForZoomLevel('y', currZoomLevel);\r\n\r\n currSlide.setZoomLevel(currZoomLevel);\r\n currSlide.applyCurrentZoomPan();\r\n }\r\n\r\n end() {\r\n const { pswp } = this;\r\n const { currSlide } = pswp;\r\n if (currSlide.currZoomLevel < currSlide.zoomLevels.initial\r\n && !this._wasOverFitZoomLevel\r\n && pswp.options.pinchToClose) {\r\n pswp.close();\r\n } else {\r\n this.correctZoomPan();\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {'x' | 'y'} axis\r\n * @param {number} currZoomLevel\r\n */\r\n _calculatePanForZoomLevel(axis, currZoomLevel) {\r\n const zoomFactor = currZoomLevel / this._startZoomLevel;\r\n return this._zoomPoint[axis]\r\n - ((this._startZoomPoint[axis] - this._startPan[axis]) * zoomFactor);\r\n }\r\n\r\n /**\r\n * Correct currZoomLevel and pan if they are\r\n * beyond minimum or maximum values.\r\n * With animation.\r\n *\r\n * @param {boolean=} ignoreGesture\r\n * Wether gesture coordinates should be ignored when calculating destination pan position.\r\n */\r\n correctZoomPan(ignoreGesture) {\r\n const { pswp } = this;\r\n const { currSlide } = pswp;\r\n\r\n if (!currSlide.isZoomable()) {\r\n return;\r\n }\r\n\r\n if (this._zoomPoint.x === undefined) {\r\n ignoreGesture = true;\r\n }\r\n\r\n const prevZoomLevel = currSlide.currZoomLevel;\r\n\r\n /** @type {number} */\r\n let destinationZoomLevel;\r\n let currZoomLevelNeedsChange = true;\r\n\r\n if (prevZoomLevel < currSlide.zoomLevels.initial) {\r\n destinationZoomLevel = currSlide.zoomLevels.initial;\r\n // zoom to min\r\n } else if (prevZoomLevel > currSlide.zoomLevels.max) {\r\n destinationZoomLevel = currSlide.zoomLevels.max;\r\n // zoom to max\r\n } else {\r\n currZoomLevelNeedsChange = false;\r\n destinationZoomLevel = prevZoomLevel;\r\n }\r\n\r\n const initialBgOpacity = pswp.bgOpacity;\r\n const restoreBgOpacity = pswp.bgOpacity < 1;\r\n\r\n const initialPan = equalizePoints({}, currSlide.pan);\r\n let destinationPan = equalizePoints({}, initialPan);\r\n\r\n if (ignoreGesture) {\r\n this._zoomPoint.x = 0;\r\n this._zoomPoint.y = 0;\r\n this._startZoomPoint.x = 0;\r\n this._startZoomPoint.y = 0;\r\n this._startZoomLevel = prevZoomLevel;\r\n equalizePoints(this._startPan, initialPan);\r\n }\r\n\r\n if (currZoomLevelNeedsChange) {\r\n destinationPan = {\r\n x: this._calculatePanForZoomLevel('x', destinationZoomLevel),\r\n y: this._calculatePanForZoomLevel('y', destinationZoomLevel)\r\n };\r\n }\r\n\r\n // set zoom level, so pan bounds are updated according to it\r\n currSlide.setZoomLevel(destinationZoomLevel);\r\n\r\n destinationPan = {\r\n x: currSlide.bounds.correctPan('x', destinationPan.x),\r\n y: currSlide.bounds.correctPan('y', destinationPan.y)\r\n };\r\n\r\n // return zoom level and its bounds to initial\r\n currSlide.setZoomLevel(prevZoomLevel);\r\n\r\n let panNeedsChange = true;\r\n if (pointsEqual(destinationPan, initialPan)) {\r\n panNeedsChange = false;\r\n }\r\n\r\n if (!panNeedsChange && !currZoomLevelNeedsChange && !restoreBgOpacity) {\r\n // update resolution after gesture\r\n currSlide._setResolution(destinationZoomLevel);\r\n currSlide.applyCurrentZoomPan();\r\n\r\n // nothing to animate\r\n return;\r\n }\r\n\r\n pswp.animations.stopAllPan();\r\n\r\n pswp.animations.startSpring({\r\n isPan: true,\r\n start: 0,\r\n end: 1000,\r\n velocity: 0,\r\n dampingRatio: 1,\r\n naturalFrequency: 40,\r\n onUpdate: (now) => {\r\n now /= 1000; // 0 - start, 1 - end\r\n\r\n if (panNeedsChange || currZoomLevelNeedsChange) {\r\n if (panNeedsChange) {\r\n currSlide.pan.x = initialPan.x + (destinationPan.x - initialPan.x) * now;\r\n currSlide.pan.y = initialPan.y + (destinationPan.y - initialPan.y) * now;\r\n }\r\n\r\n if (currZoomLevelNeedsChange) {\r\n const newZoomLevel = prevZoomLevel\r\n + (destinationZoomLevel - prevZoomLevel) * now;\r\n currSlide.setZoomLevel(newZoomLevel);\r\n }\r\n\r\n currSlide.applyCurrentZoomPan();\r\n }\r\n\r\n // Restore background opacity\r\n if (restoreBgOpacity && pswp.bgOpacity < 1) {\r\n // We clamp opacity to keep it between 0 and 1.\r\n // As progress ratio can be larger than 1 due to overshoot,\r\n // and we do not want to bounce opacity.\r\n pswp.applyBgOpacity(clamp(\r\n initialBgOpacity + (1 - initialBgOpacity) * now, 0, 1\r\n ));\r\n }\r\n },\r\n onComplete: () => {\r\n // update resolution after transition ends\r\n currSlide._setResolution(destinationZoomLevel);\r\n currSlide.applyCurrentZoomPan();\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport default ZoomHandler;\r\n","/**\r\n * @template T\r\n * @template P\r\n * @typedef {import('../types.js').AddPostfix} AddPostfix\r\n */\r\n\r\n/** @typedef {import('./gestures.js').default} Gestures */\r\n\r\n/** @typedef {'imageClick' | 'bgClick' | 'tap' | 'doubleTap'} Actions */\r\n/** @typedef {{ x?: number; y?: number }} Point */\r\n\r\n/**\r\n * Whether the tap was performed on the main slide\r\n * (rather than controls or caption).\r\n *\r\n * @param {PointerEvent} event\r\n */\r\nfunction didTapOnMainContent(event) {\r\n return !!(/** @type {HTMLElement} */ (event.target).closest('.pswp__container'));\r\n}\r\n\r\n/**\r\n * Tap, double-tap handler.\r\n */\r\nclass TapHandler {\r\n /**\r\n * @param {Gestures} gestures\r\n */\r\n constructor(gestures) {\r\n this.gestures = gestures;\r\n }\r\n\r\n /**\r\n * @param {Point} point\r\n * @param {PointerEvent} originalEvent\r\n */\r\n click(point, originalEvent) {\r\n const targetClassList = /** @type {HTMLElement} */ (originalEvent.target).classList;\r\n const isImageClick = targetClassList.contains('pswp__img');\r\n const isBackgroundClick = targetClassList.contains('pswp__item')\r\n || targetClassList.contains('pswp__zoom-wrap');\r\n\r\n if (isImageClick) {\r\n this._doClickOrTapAction('imageClick', point, originalEvent);\r\n } else if (isBackgroundClick) {\r\n this._doClickOrTapAction('bgClick', point, originalEvent);\r\n }\r\n }\r\n\r\n /**\r\n * @param {Point} point\r\n * @param {PointerEvent} originalEvent\r\n */\r\n tap(point, originalEvent) {\r\n if (didTapOnMainContent(originalEvent)) {\r\n this._doClickOrTapAction('tap', point, originalEvent);\r\n }\r\n }\r\n\r\n /**\r\n * @param {Point} point\r\n * @param {PointerEvent} originalEvent\r\n */\r\n doubleTap(point, originalEvent) {\r\n if (didTapOnMainContent(originalEvent)) {\r\n this._doClickOrTapAction('doubleTap', point, originalEvent);\r\n }\r\n }\r\n\r\n /**\r\n * @param {Actions} actionName\r\n * @param {Point} point\r\n * @param {PointerEvent} originalEvent\r\n */\r\n _doClickOrTapAction(actionName, point, originalEvent) {\r\n const { pswp } = this.gestures;\r\n const { currSlide } = pswp;\r\n const actionFullName = /** @type {AddPostfix} */ (actionName + 'Action');\r\n const optionValue = pswp.options[actionFullName];\r\n\r\n if (pswp.dispatch(actionFullName, { point, originalEvent }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (typeof optionValue === 'function') {\r\n optionValue.call(pswp, point, originalEvent);\r\n return;\r\n }\r\n\r\n switch (optionValue) {\r\n case 'close':\r\n case 'next':\r\n pswp[optionValue]();\r\n break;\r\n case 'zoom':\r\n currSlide.toggleZoom(point);\r\n break;\r\n case 'zoom-or-close':\r\n // by default click zooms current image,\r\n // if it can not be zoomed - gallery will be closed\r\n if (currSlide.isZoomable()\r\n && currSlide.zoomLevels.secondary !== currSlide.zoomLevels.initial) {\r\n currSlide.toggleZoom(point);\r\n } else if (pswp.options.clickToCloseNonZoomable) {\r\n pswp.close();\r\n }\r\n break;\r\n case 'toggle-controls':\r\n this.gestures.pswp.element.classList.toggle('pswp--ui-visible');\r\n // if (_controlsVisible) {\r\n // _ui.hideControls();\r\n // } else {\r\n // _ui.showControls();\r\n // }\r\n break;\r\n }\r\n }\r\n}\r\n\r\nexport default TapHandler;\r\n","import {\r\n equalizePoints, pointsEqual, getDistanceBetween\r\n} from '../util/util.js';\r\n\r\nimport DragHandler from './drag-handler.js';\r\nimport ZoomHandler from './zoom-handler.js';\r\nimport TapHandler from './tap-handler.js';\r\n\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('../photoswipe.js').Point} Point */\r\n\r\n// How far should user should drag\r\n// until we can determine that the gesture is swipe and its direction\r\nconst AXIS_SWIPE_HYSTERISIS = 10;\r\n//const PAN_END_FRICTION = 0.35;\r\n\r\nconst DOUBLE_TAP_DELAY = 300; // ms\r\nconst MIN_TAP_DISTANCE = 25; // px\r\n\r\n/**\r\n * Gestures class bind touch, pointer or mouse events\r\n * and emits drag to drag-handler and zoom events zoom-handler.\r\n *\r\n * Drag and zoom events are emited in requestAnimationFrame,\r\n * and only when one of pointers was actually changed.\r\n */\r\nclass Gestures {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(pswp) {\r\n this.pswp = pswp;\r\n\r\n /** @type {'x' | 'y'} */\r\n this.dragAxis = undefined;\r\n\r\n // point objects are defined once and reused\r\n // PhotoSwipe keeps track only of two pointers, others are ignored\r\n /** @type {Point} */\r\n this.p1 = {}; // the first pressed pointer\r\n /** @type {Point} */\r\n this.p2 = {}; // the second pressed pointer\r\n /** @type {Point} */\r\n this.prevP1 = {};\r\n /** @type {Point} */\r\n this.prevP2 = {};\r\n /** @type {Point} */\r\n this.startP1 = {};\r\n /** @type {Point} */\r\n this.startP2 = {};\r\n /** @type {Point} */\r\n this.velocity = {};\r\n\r\n /** @type {Point} */\r\n this._lastStartP1 = {};\r\n /** @type {Point} */\r\n this._intervalP1 = {};\r\n this._numActivePoints = 0;\r\n /** @type {Point[]} */\r\n this._ongoingPointers = [];\r\n\r\n this._touchEventEnabled = 'ontouchstart' in window;\r\n this._pointerEventEnabled = !!(window.PointerEvent);\r\n this.supportsTouch = this._touchEventEnabled\r\n || (this._pointerEventEnabled && navigator.maxTouchPoints > 1);\r\n\r\n if (!this.supportsTouch) {\r\n // disable pan to next slide for non-touch devices\r\n pswp.options.allowPanToNext = false;\r\n }\r\n\r\n this.drag = new DragHandler(this);\r\n this.zoomLevels = new ZoomHandler(this);\r\n this.tapHandler = new TapHandler(this);\r\n\r\n pswp.on('bindEvents', () => {\r\n pswp.events.add(pswp.scrollWrap, 'click', e => this._onClick(e));\r\n\r\n if (this._pointerEventEnabled) {\r\n this._bindEvents('pointer', 'down', 'up', 'cancel');\r\n } else if (this._touchEventEnabled) {\r\n this._bindEvents('touch', 'start', 'end', 'cancel');\r\n\r\n // In previous versions we also bound mouse event here,\r\n // in case device supports both touch and mouse events,\r\n // but newer versions of browsers now support PointerEvent.\r\n\r\n // on iOS10 if you bind touchmove/end after touchstart,\r\n // and you don't preventDefault touchstart (which PhotoSwipe does),\r\n // preventDefault will have no effect on touchmove and touchend.\r\n // Unless you bind it previously.\r\n pswp.scrollWrap.ontouchmove = () => {}; // eslint-disable-line\r\n pswp.scrollWrap.ontouchend = () => {}; // eslint-disable-line\r\n } else {\r\n this._bindEvents('mouse', 'down', 'up');\r\n }\r\n });\r\n }\r\n\r\n /**\r\n *\r\n * @param {'mouse' | 'touch' | 'pointer'} pref\r\n * @param {'down' | 'start'} down\r\n * @param {'up' | 'end'} up\r\n * @param {'cancel'} [cancel]\r\n */\r\n _bindEvents(pref, down, up, cancel) {\r\n const { pswp } = this;\r\n const { events } = pswp;\r\n\r\n const cancelEvent = cancel ? pref + cancel : '';\r\n\r\n events.add(pswp.scrollWrap, pref + down, this.onPointerDown.bind(this));\r\n events.add(window, pref + 'move', this.onPointerMove.bind(this));\r\n events.add(window, pref + up, this.onPointerUp.bind(this));\r\n if (cancelEvent) {\r\n events.add(pswp.scrollWrap, cancelEvent, this.onPointerUp.bind(this));\r\n }\r\n }\r\n\r\n /**\r\n * @param {PointerEvent} e\r\n */\r\n onPointerDown(e) {\r\n // We do not call preventDefault for touch events\r\n // to allow browser to show native dialog on longpress\r\n // (the one that allows to save image or open it in new tab).\r\n //\r\n // Desktop Safari allows to drag images when preventDefault isn't called on mousedown,\r\n // even though preventDefault IS called on mousemove. That's why we preventDefault mousedown.\r\n let isMousePointer;\r\n if (e.type === 'mousedown' || e.pointerType === 'mouse') {\r\n isMousePointer = true;\r\n }\r\n\r\n // Allow dragging only via left mouse button.\r\n // http://www.quirksmode.org/js/events_properties.html\r\n // https://developer.mozilla.org/en-US/docs/Web/API/event.button\r\n if (isMousePointer && e.button > 0) {\r\n return;\r\n }\r\n\r\n const { pswp } = this;\r\n\r\n // if PhotoSwipe is opening or closing\r\n if (!pswp.opener.isOpen) {\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n if (pswp.dispatch('pointerDown', { originalEvent: e }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (isMousePointer) {\r\n pswp.mouseDetected();\r\n\r\n // preventDefault mouse event to prevent\r\n // browser image drag feature\r\n this._preventPointerEventBehaviour(e);\r\n }\r\n\r\n pswp.animations.stopAll();\r\n\r\n this._updatePoints(e, 'down');\r\n\r\n this.pointerDown = true;\r\n\r\n if (this._numActivePoints === 1) {\r\n this.dragAxis = null;\r\n // we need to store initial point to determine the main axis,\r\n // drag is activated only after the axis is determined\r\n equalizePoints(this.startP1, this.p1);\r\n }\r\n\r\n if (this._numActivePoints > 1) {\r\n // Tap or double tap should not trigger if more than one pointer\r\n this._clearTapTimer();\r\n this.isMultitouch = true;\r\n } else {\r\n this.isMultitouch = false;\r\n }\r\n }\r\n\r\n /**\r\n * @param {PointerEvent} e\r\n */\r\n onPointerMove(e) {\r\n e.preventDefault(); // always preventDefault move event\r\n\r\n if (!this._numActivePoints) {\r\n return;\r\n }\r\n\r\n this._updatePoints(e, 'move');\r\n\r\n if (this.pswp.dispatch('pointerMove', { originalEvent: e }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (this._numActivePoints === 1 && !this.isDragging) {\r\n if (!this.dragAxis) {\r\n this._calculateDragDirection();\r\n }\r\n\r\n // Drag axis was detected, emit drag.start\r\n if (this.dragAxis && !this.isDragging) {\r\n if (this.isZooming) {\r\n this.isZooming = false;\r\n this.zoomLevels.end();\r\n }\r\n\r\n this.isDragging = true;\r\n this._clearTapTimer(); // Tap can not trigger after drag\r\n\r\n // Adjust starting point\r\n this._updateStartPoints();\r\n this._intervalTime = Date.now();\r\n //this._startTime = this._intervalTime;\r\n this._velocityCalculated = false;\r\n equalizePoints(this._intervalP1, this.p1);\r\n this.velocity.x = 0;\r\n this.velocity.y = 0;\r\n this.drag.start();\r\n\r\n this._rafStopLoop();\r\n this._rafRenderLoop();\r\n }\r\n } else if (this._numActivePoints > 1 && !this.isZooming) {\r\n this._finishDrag();\r\n\r\n this.isZooming = true;\r\n\r\n // Adjust starting points\r\n this._updateStartPoints();\r\n\r\n this.zoomLevels.start();\r\n\r\n this._rafStopLoop();\r\n this._rafRenderLoop();\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n _finishDrag() {\r\n if (this.isDragging) {\r\n this.isDragging = false;\r\n\r\n // Try to calculate velocity,\r\n // if it wasn't calculated yet in drag.change\r\n if (!this._velocityCalculated) {\r\n this._updateVelocity(true);\r\n }\r\n\r\n this.drag.end();\r\n this.dragAxis = null;\r\n }\r\n }\r\n\r\n /**\r\n * @param {PointerEvent} e\r\n */\r\n onPointerUp(e) {\r\n if (!this._numActivePoints) {\r\n return;\r\n }\r\n\r\n this._updatePoints(e, 'up');\r\n\r\n if (this.pswp.dispatch('pointerUp', { originalEvent: e }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (this._numActivePoints === 0) {\r\n this.pointerDown = false;\r\n this._rafStopLoop();\r\n\r\n if (this.isDragging) {\r\n this._finishDrag();\r\n } else if (!this.isZooming && !this.isMultitouch) {\r\n //this.zoomLevels.correctZoomPan();\r\n this._finishTap(e);\r\n }\r\n }\r\n\r\n if (this._numActivePoints < 2 && this.isZooming) {\r\n this.isZooming = false;\r\n this.zoomLevels.end();\r\n\r\n if (this._numActivePoints === 1) {\r\n // Since we have 1 point left, we need to reinitiate drag\r\n this.dragAxis = null;\r\n this._updateStartPoints();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n _rafRenderLoop() {\r\n if (this.isDragging || this.isZooming) {\r\n this._updateVelocity();\r\n\r\n if (this.isDragging) {\r\n // make sure that pointer moved since the last update\r\n if (!pointsEqual(this.p1, this.prevP1)) {\r\n this.drag.change();\r\n }\r\n } else /* if (this.isZooming) */ {\r\n if (!pointsEqual(this.p1, this.prevP1)\r\n || !pointsEqual(this.p2, this.prevP2)) {\r\n this.zoomLevels.change();\r\n }\r\n }\r\n\r\n this._updatePrevPoints();\r\n this.raf = requestAnimationFrame(this._rafRenderLoop.bind(this));\r\n }\r\n }\r\n\r\n /**\r\n * Update velocity at 50ms interval\r\n *\r\n * @param {boolean=} force\r\n */\r\n _updateVelocity(force) {\r\n const time = Date.now();\r\n const duration = time - this._intervalTime;\r\n\r\n if (duration < 50 && !force) {\r\n return;\r\n }\r\n\r\n\r\n this.velocity.x = this._getVelocity('x', duration);\r\n this.velocity.y = this._getVelocity('y', duration);\r\n\r\n this._intervalTime = time;\r\n equalizePoints(this._intervalP1, this.p1);\r\n this._velocityCalculated = true;\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {PointerEvent} e\r\n */\r\n _finishTap(e) {\r\n const { mainScroll } = this.pswp;\r\n\r\n // Do not trigger tap events if main scroll is shifted\r\n if (mainScroll.isShifted()) {\r\n // restore main scroll position\r\n // (usually happens if stopped in the middle of animation)\r\n mainScroll.moveIndexBy(0, true);\r\n return;\r\n }\r\n\r\n // Do not trigger tap for touchcancel or pointercancel\r\n if (e.type.indexOf('cancel') > 0) {\r\n return;\r\n }\r\n\r\n // Trigger click instead of tap for mouse events\r\n if (e.type === 'mouseup' || e.pointerType === 'mouse') {\r\n this.tapHandler.click(this.startP1, e);\r\n return;\r\n }\r\n\r\n // Disable delay if there is no doubleTapAction\r\n const tapDelay = this.pswp.options.doubleTapAction ? DOUBLE_TAP_DELAY : 0;\r\n\r\n // If tapTimer is defined - we tapped recently,\r\n // check if the current tap is close to the previous one,\r\n // if yes - trigger double tap\r\n if (this._tapTimer) {\r\n this._clearTapTimer();\r\n // Check if two taps were more or less on the same place\r\n if (getDistanceBetween(this._lastStartP1, this.startP1) < MIN_TAP_DISTANCE) {\r\n this.tapHandler.doubleTap(this.startP1, e);\r\n }\r\n } else {\r\n equalizePoints(this._lastStartP1, this.startP1);\r\n this._tapTimer = setTimeout(() => {\r\n this.tapHandler.tap(this.startP1, e);\r\n this._clearTapTimer();\r\n }, tapDelay);\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n _clearTapTimer() {\r\n if (this._tapTimer) {\r\n clearTimeout(this._tapTimer);\r\n this._tapTimer = null;\r\n }\r\n }\r\n\r\n /**\r\n * Get velocity for axis\r\n *\r\n * @private\r\n * @param {'x' | 'y'} axis\r\n * @param {number} duration\r\n */\r\n _getVelocity(axis, duration) {\r\n // displacement is like distance, but can be negative.\r\n const displacement = this.p1[axis] - this._intervalP1[axis];\r\n\r\n if (Math.abs(displacement) > 1 && duration > 5) {\r\n return displacement / duration;\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n _rafStopLoop() {\r\n if (this.raf) {\r\n cancelAnimationFrame(this.raf);\r\n this.raf = null;\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {PointerEvent} e\r\n */\r\n _preventPointerEventBehaviour(e) {\r\n // TODO find a way to disable e.preventDefault on some elements\r\n // via event or some class or something\r\n e.preventDefault();\r\n return true;\r\n }\r\n\r\n /**\r\n * Parses and normalizes points from the touch, mouse or pointer event.\r\n * Updates p1 and p2.\r\n *\r\n * @private\r\n * @param {PointerEvent | TouchEvent} e\r\n * @param {'up' | 'down' | 'move'} pointerType Normalized pointer type\r\n */\r\n _updatePoints(e, pointerType) {\r\n if (this._pointerEventEnabled) {\r\n const pointerEvent = /** @type {PointerEvent} */ (e);\r\n // Try to find the current pointer in ongoing pointers by its ID\r\n const pointerIndex = this._ongoingPointers.findIndex((ongoingPoiner) => {\r\n return ongoingPoiner.id === pointerEvent.pointerId;\r\n });\r\n\r\n if (pointerType === 'up' && pointerIndex > -1) {\r\n // release the pointer - remove it from ongoing\r\n this._ongoingPointers.splice(pointerIndex, 1);\r\n } else if (pointerType === 'down' && pointerIndex === -1) {\r\n // add new pointer\r\n this._ongoingPointers.push(this._convertEventPosToPoint(pointerEvent, {}));\r\n } else if (pointerIndex > -1) {\r\n // update existing pointer\r\n this._convertEventPosToPoint(pointerEvent, this._ongoingPointers[pointerIndex]);\r\n }\r\n\r\n this._numActivePoints = this._ongoingPointers.length;\r\n\r\n // update points that PhotoSwipe uses\r\n // to calculate position and scale\r\n if (this._numActivePoints > 0) {\r\n equalizePoints(this.p1, this._ongoingPointers[0]);\r\n }\r\n\r\n if (this._numActivePoints > 1) {\r\n equalizePoints(this.p2, this._ongoingPointers[1]);\r\n }\r\n } else {\r\n const touchEvent = /** @type {TouchEvent} */ (e);\r\n\r\n this._numActivePoints = 0;\r\n if (touchEvent.type.indexOf('touch') > -1) {\r\n // Touch Event\r\n // https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent\r\n if (touchEvent.touches && touchEvent.touches.length > 0) {\r\n this._convertEventPosToPoint(touchEvent.touches[0], this.p1);\r\n this._numActivePoints++;\r\n if (touchEvent.touches.length > 1) {\r\n this._convertEventPosToPoint(touchEvent.touches[1], this.p2);\r\n this._numActivePoints++;\r\n }\r\n }\r\n } else {\r\n // Mouse Event\r\n this._convertEventPosToPoint(/** @type {PointerEvent} */ (e), this.p1);\r\n if (pointerType === 'up') {\r\n // clear all points on mouseup\r\n this._numActivePoints = 0;\r\n } else {\r\n this._numActivePoints++;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // update points that were used during previous rAF tick\r\n _updatePrevPoints() {\r\n equalizePoints(this.prevP1, this.p1);\r\n equalizePoints(this.prevP2, this.p2);\r\n }\r\n\r\n // update points at the start of gesture\r\n _updateStartPoints() {\r\n equalizePoints(this.startP1, this.p1);\r\n equalizePoints(this.startP2, this.p2);\r\n this._updatePrevPoints();\r\n }\r\n\r\n _calculateDragDirection() {\r\n if (this.pswp.mainScroll.isShifted()) {\r\n // if main scroll position is shifted – direction is always horizontal\r\n this.dragAxis = 'x';\r\n } else {\r\n // calculate delta of the last touchmove tick\r\n const diff = Math.abs(this.p1.x - this.startP1.x) - Math.abs(this.p1.y - this.startP1.y);\r\n\r\n if (diff !== 0) {\r\n // check if pointer was shifted horizontally or vertically\r\n const axisToCheck = diff > 0 ? 'x' : 'y';\r\n\r\n if (Math.abs(this.p1[axisToCheck] - this.startP1[axisToCheck]) >= AXIS_SWIPE_HYSTERISIS) {\r\n this.dragAxis = axisToCheck;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Converts touch, pointer or mouse event\r\n * to PhotoSwipe point.\r\n *\r\n * @private\r\n * @param {Touch | PointerEvent} e\r\n * @param {Point} p\r\n */\r\n _convertEventPosToPoint(e, p) {\r\n p.x = e.pageX - this.pswp.offset.x;\r\n p.y = e.pageY - this.pswp.offset.y;\r\n\r\n if ('pointerId' in e) {\r\n p.id = e.pointerId;\r\n } else if (e.identifier !== undefined) {\r\n p.id = e.identifier;\r\n }\r\n\r\n return p;\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {PointerEvent} e\r\n */\r\n _onClick(e) {\r\n // Do not allow click event to pass through after drag\r\n if (this.pswp.mainScroll.isShifted()) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n }\r\n}\r\n\r\nexport default Gestures;\r\n","import {\r\n setTransform,\r\n createElement,\r\n} from './util/util.js';\r\n\r\n/** @typedef {import('./photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('./slide/slide.js').default} Slide */\r\n\r\n/** @typedef {{ el: HTMLDivElement; slide?: Slide }} ItemHolder */\r\n\r\nconst MAIN_SCROLL_END_FRICTION = 0.35;\r\n\r\n\r\n// const MIN_SWIPE_TRANSITION_DURATION = 250;\r\n// const MAX_SWIPE_TRABSITION_DURATION = 500;\r\n// const DEFAULT_SWIPE_TRANSITION_DURATION = 333;\r\n\r\n/**\r\n * Handles movement of the main scrolling container\r\n * (for example, it repositions when user swipes left or right).\r\n *\r\n * Also stores its state.\r\n */\r\nclass MainScroll {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(pswp) {\r\n this.pswp = pswp;\r\n this.x = 0;\r\n\r\n /** @type {number} */\r\n this.slideWidth = undefined;\r\n\r\n /** @type {ItemHolder[]} */\r\n this.itemHolders = undefined;\r\n\r\n this.resetPosition();\r\n }\r\n\r\n /**\r\n * Position the scroller and slide containers\r\n * according to viewport size.\r\n *\r\n * @param {boolean=} resizeSlides Whether slides content should resized\r\n */\r\n resize(resizeSlides) {\r\n const { pswp } = this;\r\n const newSlideWidth = Math.round(\r\n pswp.viewportSize.x + pswp.viewportSize.x * pswp.options.spacing\r\n );\r\n // Mobile browsers might trigger a resize event during a gesture.\r\n // (due to toolbar appearing or hiding).\r\n // Avoid re-adjusting main scroll position if width wasn't changed\r\n const slideWidthChanged = (newSlideWidth !== this.slideWidth);\r\n\r\n if (slideWidthChanged) {\r\n this.slideWidth = newSlideWidth;\r\n this.moveTo(this.getCurrSlideX());\r\n }\r\n\r\n this.itemHolders.forEach((itemHolder, index) => {\r\n if (slideWidthChanged) {\r\n setTransform(itemHolder.el, (index + this._containerShiftIndex)\r\n * this.slideWidth);\r\n }\r\n\r\n if (resizeSlides && itemHolder.slide) {\r\n itemHolder.slide.resize();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Reset X position of the main scroller to zero\r\n */\r\n resetPosition() {\r\n // Position on the main scroller (offset)\r\n // it is independent from slide index\r\n this._currPositionIndex = 0;\r\n this._prevPositionIndex = 0;\r\n\r\n // This will force recalculation of size on next resize()\r\n this.slideWidth = 0;\r\n\r\n // _containerShiftIndex*viewportSize will give you amount of transform of the current slide\r\n this._containerShiftIndex = -1;\r\n }\r\n\r\n /**\r\n * Create and append array of three items\r\n * that hold data about slides in DOM\r\n */\r\n appendHolders() {\r\n this.itemHolders = [];\r\n\r\n // append our three slide holders -\r\n // previous, current, and next\r\n for (let i = 0; i < 3; i++) {\r\n const el = createElement('pswp__item', false, this.pswp.container);\r\n\r\n // hide nearby item holders until initial zoom animation finishes (to avoid extra Paints)\r\n el.style.display = (i === 1) ? 'block' : 'none';\r\n\r\n this.itemHolders.push({\r\n el,\r\n //index: -1\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Whether the main scroll can be horizontally swiped to the next or previous slide.\r\n */\r\n canBeSwiped() {\r\n return this.pswp.getNumItems() > 1;\r\n }\r\n\r\n /**\r\n * Move main scroll by X amount of slides.\r\n * For example:\r\n * `-1` will move to the previous slide,\r\n * `0` will reset the scroll position of the current slide,\r\n * `3` will move three slides forward\r\n *\r\n * If loop option is enabled - index will be automatically looped too,\r\n * (for example `-1` will move to the last slide of the gallery).\r\n *\r\n * @param {number} diff\r\n * @param {boolean=} animate\r\n * @param {number=} velocityX\r\n * @returns {boolean} whether index was changed or not\r\n */\r\n moveIndexBy(diff, animate, velocityX) {\r\n const { pswp } = this;\r\n let newIndex = pswp.potentialIndex + diff;\r\n const numSlides = pswp.getNumItems();\r\n\r\n if (pswp.canLoop()) {\r\n newIndex = pswp.getLoopedIndex(newIndex);\r\n const distance = (diff + numSlides) % numSlides;\r\n if (distance <= numSlides / 2) {\r\n // go forward\r\n diff = distance;\r\n } else {\r\n // go backwards\r\n diff = distance - numSlides;\r\n }\r\n } else {\r\n if (newIndex < 0) {\r\n newIndex = 0;\r\n } else if (newIndex >= numSlides) {\r\n newIndex = numSlides - 1;\r\n }\r\n diff = newIndex - pswp.potentialIndex;\r\n }\r\n\r\n pswp.potentialIndex = newIndex;\r\n this._currPositionIndex -= diff;\r\n\r\n pswp.animations.stopMainScroll();\r\n\r\n const destinationX = this.getCurrSlideX();\r\n if (!animate) {\r\n this.moveTo(destinationX);\r\n this.updateCurrItem();\r\n } else {\r\n pswp.animations.startSpring({\r\n isMainScroll: true,\r\n start: this.x,\r\n end: destinationX,\r\n velocity: velocityX || 0,\r\n naturalFrequency: 30,\r\n dampingRatio: 1, //0.7,\r\n onUpdate: (x) => {\r\n this.moveTo(x);\r\n },\r\n onComplete: () => {\r\n this.updateCurrItem();\r\n pswp.appendHeavy();\r\n }\r\n });\r\n\r\n let currDiff = pswp.potentialIndex - pswp.currIndex;\r\n if (pswp.canLoop()) {\r\n const currDistance = (currDiff + numSlides) % numSlides;\r\n if (currDistance <= numSlides / 2) {\r\n // go forward\r\n currDiff = currDistance;\r\n } else {\r\n // go backwards\r\n currDiff = currDistance - numSlides;\r\n }\r\n }\r\n\r\n // Force-append new slides during transition\r\n // if difference between slides is more than 1\r\n if (Math.abs(currDiff) > 1) {\r\n this.updateCurrItem();\r\n }\r\n }\r\n\r\n if (diff) {\r\n return true;\r\n }\r\n }\r\n\r\n /**\r\n * X position of the main scroll for the current slide\r\n * (ignores position during dragging)\r\n */\r\n getCurrSlideX() {\r\n return this.slideWidth * this._currPositionIndex;\r\n }\r\n\r\n /**\r\n * Whether scroll position is shifted.\r\n * For example, it will return true if the scroll is being dragged or animated.\r\n */\r\n isShifted() {\r\n return this.x !== this.getCurrSlideX();\r\n }\r\n\r\n /**\r\n * Update slides X positions and set their content\r\n */\r\n updateCurrItem() {\r\n const { pswp } = this;\r\n const positionDifference = this._prevPositionIndex - this._currPositionIndex;\r\n\r\n if (!positionDifference) {\r\n return;\r\n }\r\n\r\n this._prevPositionIndex = this._currPositionIndex;\r\n\r\n pswp.currIndex = pswp.potentialIndex;\r\n\r\n let diffAbs = Math.abs(positionDifference);\r\n let tempHolder;\r\n\r\n if (diffAbs >= 3) {\r\n this._containerShiftIndex += positionDifference + (positionDifference > 0 ? -3 : 3);\r\n diffAbs = 3;\r\n }\r\n\r\n for (let i = 0; i < diffAbs; i++) {\r\n if (positionDifference > 0) {\r\n tempHolder = this.itemHolders.shift();\r\n this.itemHolders[2] = tempHolder; // move first to last\r\n\r\n this._containerShiftIndex++;\r\n\r\n setTransform(tempHolder.el, (this._containerShiftIndex + 2) * this.slideWidth);\r\n\r\n pswp.setContent(tempHolder, (pswp.currIndex - diffAbs) + i + 2);\r\n } else {\r\n tempHolder = this.itemHolders.pop();\r\n this.itemHolders.unshift(tempHolder); // move last to first\r\n\r\n this._containerShiftIndex--;\r\n\r\n setTransform(tempHolder.el, this._containerShiftIndex * this.slideWidth);\r\n\r\n pswp.setContent(tempHolder, (pswp.currIndex + diffAbs) - i - 2);\r\n }\r\n }\r\n\r\n // Reset transfrom every 50ish navigations in one direction.\r\n //\r\n // Otherwise transform will keep growing indefinitely,\r\n // which might cause issues as browsers have a maximum transform limit.\r\n // I wasn't able to reach it, but just to be safe.\r\n // This should not cause noticable lag.\r\n if (Math.abs(this._containerShiftIndex) > 50 && !this.isShifted()) {\r\n this.resetPosition();\r\n this.resize();\r\n }\r\n\r\n // Pan transition might be running (and consntantly updating pan position)\r\n pswp.animations.stopAllPan();\r\n\r\n this.itemHolders.forEach((itemHolder, i) => {\r\n if (itemHolder.slide) {\r\n // Slide in the 2nd holder is always active\r\n itemHolder.slide.setIsActive(i === 1);\r\n }\r\n });\r\n\r\n pswp.currSlide = this.itemHolders[1].slide;\r\n pswp.contentLoader.updateLazy(positionDifference);\r\n\r\n pswp.currSlide.applyCurrentZoomPan();\r\n pswp.dispatch('change');\r\n }\r\n\r\n /**\r\n * Move the X position of the main scroll container\r\n *\r\n * @param {number} x\r\n * @param {boolean=} dragging\r\n */\r\n moveTo(x, dragging) {\r\n /** @type {number} */\r\n let newSlideIndexOffset;\r\n /** @type {number} */\r\n let delta;\r\n\r\n if (!this.pswp.canLoop() && dragging) {\r\n // Apply friction\r\n newSlideIndexOffset = ((this.slideWidth * this._currPositionIndex) - x) / this.slideWidth;\r\n newSlideIndexOffset += this.pswp.currIndex;\r\n delta = Math.round(x - this.x);\r\n\r\n if ((newSlideIndexOffset < 0 && delta > 0)\r\n || (newSlideIndexOffset >= this.pswp.getNumItems() - 1 && delta < 0)) {\r\n x = this.x + (delta * MAIN_SCROLL_END_FRICTION);\r\n }\r\n }\r\n\r\n this.x = x;\r\n setTransform(this.pswp.container, x);\r\n\r\n this.pswp.dispatch('moveMainScroll', { x, dragging });\r\n }\r\n}\r\n\r\nexport default MainScroll;\r\n","import { specialKeyUsed } from './util/util.js';\r\n\r\n/** @typedef {import('./photoswipe.js').default} PhotoSwipe */\r\n\r\n/**\r\n * @template T\r\n * @typedef {import('./types.js').Methods} Methods\r\n */\r\n\r\n/**\r\n * - Manages keyboard shortcuts.\r\n * - Heps trap focus within photoswipe.\r\n */\r\nclass Keyboard {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(pswp) {\r\n this.pswp = pswp;\r\n\r\n pswp.on('bindEvents', () => {\r\n // Dialog was likely opened by keyboard if initial point is not defined\r\n if (!pswp.options.initialPointerPos) {\r\n // focus causes layout,\r\n // which causes lag during the animation,\r\n // that's why we delay it until the opener transition ends\r\n this._focusRoot();\r\n }\r\n\r\n pswp.events.add(document, 'focusin', this._onFocusIn.bind(this));\r\n pswp.events.add(document, 'keydown', this._onKeyDown.bind(this));\r\n });\r\n\r\n const lastActiveElement = /** @type {HTMLElement} */ (document.activeElement);\r\n pswp.on('destroy', () => {\r\n if (pswp.options.returnFocus\r\n && lastActiveElement\r\n && this._wasFocused) {\r\n lastActiveElement.focus();\r\n }\r\n });\r\n }\r\n\r\n _focusRoot() {\r\n if (!this._wasFocused) {\r\n this.pswp.element.focus();\r\n this._wasFocused = true;\r\n }\r\n }\r\n\r\n /**\r\n * @param {KeyboardEvent} e\r\n */\r\n _onKeyDown(e) {\r\n const { pswp } = this;\r\n\r\n if (pswp.dispatch('keydown', { originalEvent: e }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (specialKeyUsed(e)) {\r\n // don't do anything if special key pressed\r\n // to prevent from overriding default browser actions\r\n // for example, in Chrome on Mac cmd+arrow-left returns to previous page\r\n return;\r\n }\r\n\r\n /** @type {Methods} */\r\n let keydownAction;\r\n /** @type {'x' | 'y'} */\r\n let axis;\r\n let isForward;\r\n\r\n switch (e.keyCode) {\r\n case 27: // esc\r\n if (pswp.options.escKey) {\r\n keydownAction = 'close';\r\n }\r\n break;\r\n case 90: // z key\r\n keydownAction = 'toggleZoom';\r\n break;\r\n case 37: // left\r\n axis = 'x';\r\n break;\r\n case 38: // top\r\n axis = 'y';\r\n break;\r\n case 39: // right\r\n axis = 'x';\r\n isForward = true;\r\n break;\r\n case 40: // bottom\r\n isForward = true;\r\n axis = 'y';\r\n break;\r\n case 9: // tab\r\n this._focusRoot();\r\n break;\r\n default:\r\n }\r\n\r\n // if left/right/top/bottom key\r\n if (axis) {\r\n // prevent page scroll\r\n e.preventDefault();\r\n\r\n const { currSlide } = pswp;\r\n\r\n if (pswp.options.arrowKeys\r\n && axis === 'x'\r\n && pswp.getNumItems() > 1) {\r\n keydownAction = isForward ? 'next' : 'prev';\r\n } else if (currSlide && currSlide.currZoomLevel > currSlide.zoomLevels.fit) {\r\n // up/down arrow keys pan the image vertically\r\n // left/right arrow keys pan horizontally.\r\n // Unless there is only one image,\r\n // or arrowKeys option is disabled\r\n currSlide.pan[axis] += isForward ? -80 : 80;\r\n currSlide.panTo(currSlide.pan.x, currSlide.pan.y);\r\n }\r\n }\r\n\r\n if (keydownAction) {\r\n e.preventDefault();\r\n pswp[keydownAction]();\r\n }\r\n }\r\n\r\n /**\r\n * Trap focus inside photoswipe\r\n *\r\n * @param {FocusEvent} e\r\n */\r\n _onFocusIn(e) {\r\n const { template } = this.pswp;\r\n if (document !== e.target\r\n && template !== e.target\r\n && !template.contains(/** @type {Node} */ (e.target))) {\r\n // focus root element\r\n template.focus();\r\n }\r\n }\r\n}\r\n\r\nexport default Keyboard;\r\n","import { setTransitionStyle, removeTransitionStyle } from './util.js';\r\n\r\nconst DEFAULT_EASING = 'cubic-bezier(.4,0,.22,1)';\r\n\r\n/** @typedef {import('./animations.js').AnimationProps} AnimationProps */\r\n\r\n/**\r\n * Runs CSS transition.\r\n */\r\nclass CSSAnimation {\r\n /**\r\n * onComplete can be unpredictable, be careful about current state\r\n *\r\n * @param {AnimationProps} props\r\n */\r\n constructor(props) {\r\n this.props = props;\r\n const {\r\n target,\r\n onComplete,\r\n transform,\r\n onFinish\r\n // opacity\r\n } = props;\r\n\r\n let {\r\n duration,\r\n easing,\r\n } = props;\r\n\r\n /** @type {() => void} */\r\n this.onFinish = onFinish;\r\n\r\n // support only transform and opacity\r\n const prop = transform ? 'transform' : 'opacity';\r\n const propValue = props[prop];\r\n\r\n /** @private */\r\n this._target = target;\r\n /** @private */\r\n this._onComplete = onComplete;\r\n\r\n duration = duration || 333;\r\n easing = easing || DEFAULT_EASING;\r\n\r\n /** @private */\r\n this._onTransitionEnd = this._onTransitionEnd.bind(this);\r\n\r\n // Using timeout hack to make sure that animation\r\n // starts even if the animated property was changed recently,\r\n // otherwise transitionend might not fire or transiton won't start.\r\n // https://drafts.csswg.org/css-transitions/#starting\r\n //\r\n // ¯\\_(ツ)_/¯\r\n /** @private */\r\n this._helperTimeout = setTimeout(() => {\r\n setTransitionStyle(target, prop, duration, easing);\r\n this._helperTimeout = setTimeout(() => {\r\n target.addEventListener('transitionend', this._onTransitionEnd, false);\r\n target.addEventListener('transitioncancel', this._onTransitionEnd, false);\r\n\r\n // Safari occasionally does not emit transitionend event\r\n // if element propery was modified during the transition,\r\n // which may be caused by resize or third party component,\r\n // using timeout as a safety fallback\r\n this._helperTimeout = setTimeout(() => {\r\n this._finalizeAnimation();\r\n }, duration + 500);\r\n target.style[prop] = propValue;\r\n }, 30); // Do not reduce this number\r\n }, 0);\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {TransitionEvent} e\r\n */\r\n _onTransitionEnd(e) {\r\n if (e.target === this._target) {\r\n this._finalizeAnimation();\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n */\r\n _finalizeAnimation() {\r\n if (!this._finished) {\r\n this._finished = true;\r\n this.onFinish();\r\n if (this._onComplete) {\r\n this._onComplete();\r\n }\r\n }\r\n }\r\n\r\n // Destroy is called automatically onFinish\r\n destroy() {\r\n if (this._helperTimeout) {\r\n clearTimeout(this._helperTimeout);\r\n }\r\n removeTransitionStyle(this._target);\r\n this._target.removeEventListener('transitionend', this._onTransitionEnd, false);\r\n this._target.removeEventListener('transitioncancel', this._onTransitionEnd, false);\r\n if (!this._finished) {\r\n this._finalizeAnimation();\r\n }\r\n }\r\n}\r\n\r\nexport default CSSAnimation;\r\n","const DEFAULT_NATURAL_FREQUENCY = 12;\r\nconst DEFAULT_DAMPING_RATIO = 0.75;\r\n\r\n/**\r\n * Spring easing helper\r\n */\r\nclass SpringEaser {\r\n /**\r\n * @param {number} initialVelocity Initial velocity, px per ms.\r\n *\r\n * @param {number} dampingRatio\r\n * Determines how bouncy animation will be.\r\n * From 0 to 1, 0 - always overshoot, 1 - do not overshoot.\r\n * \"overshoot\" refers to part of animation that\r\n * goes beyond the final value.\r\n *\r\n * @param {number} naturalFrequency\r\n * Determines how fast animation will slow down.\r\n * The higher value - the stiffer the transition will be,\r\n * and the faster it will slow down.\r\n * Recommended value from 10 to 50\r\n */\r\n constructor(initialVelocity, dampingRatio, naturalFrequency) {\r\n this.velocity = initialVelocity * 1000; // convert to \"pixels per second\"\r\n\r\n // https://en.wikipedia.org/wiki/Damping_ratio\r\n this._dampingRatio = dampingRatio || DEFAULT_DAMPING_RATIO;\r\n\r\n // https://en.wikipedia.org/wiki/Natural_frequency\r\n this._naturalFrequency = naturalFrequency || DEFAULT_NATURAL_FREQUENCY;\r\n\r\n if (this._dampingRatio < 1) {\r\n this._dampedFrequency = this._naturalFrequency\r\n * Math.sqrt(1 - this._dampingRatio * this._dampingRatio);\r\n }\r\n }\r\n\r\n /**\r\n * @param {number} deltaPosition Difference between current and end position of the animation\r\n * @param {number} deltaTime Frame duration in milliseconds\r\n *\r\n * @returns {number} Displacement, relative to the end position.\r\n */\r\n easeFrame(deltaPosition, deltaTime) {\r\n // Inspired by Apple Webkit and Android spring function implementation\r\n // https://en.wikipedia.org/wiki/Oscillation\r\n // https://en.wikipedia.org/wiki/Damping_ratio\r\n // we ignore mass (assume that it's 1kg)\r\n\r\n let displacement = 0;\r\n let coeff;\r\n\r\n deltaTime /= 1000;\r\n\r\n const naturalDumpingPow = Math.E ** (-this._dampingRatio * this._naturalFrequency * deltaTime);\r\n\r\n if (this._dampingRatio === 1) {\r\n coeff = this.velocity + this._naturalFrequency * deltaPosition;\r\n\r\n displacement = (deltaPosition + coeff * deltaTime) * naturalDumpingPow;\r\n\r\n this.velocity = displacement\r\n * (-this._naturalFrequency) + coeff\r\n * naturalDumpingPow;\r\n } else if (this._dampingRatio < 1) {\r\n coeff = (1 / this._dampedFrequency)\r\n * (this._dampingRatio * this._naturalFrequency * deltaPosition + this.velocity);\r\n\r\n const dumpedFCos = Math.cos(this._dampedFrequency * deltaTime);\r\n const dumpedFSin = Math.sin(this._dampedFrequency * deltaTime);\r\n\r\n displacement = naturalDumpingPow\r\n * (deltaPosition * dumpedFCos + coeff * dumpedFSin);\r\n\r\n this.velocity = displacement\r\n * (-this._naturalFrequency)\r\n * this._dampingRatio\r\n + naturalDumpingPow\r\n * (-this._dampedFrequency * deltaPosition * dumpedFSin\r\n + this._dampedFrequency * coeff * dumpedFCos);\r\n }\r\n\r\n // Overdamped (>1) damping ratio is not supported\r\n\r\n return displacement;\r\n }\r\n}\r\n\r\nexport default SpringEaser;\r\n","import SpringEaser from './spring-easer.js';\r\n\r\n/** @typedef {import('./animations.js').AnimationProps} AnimationProps */\r\n\r\nclass SpringAnimation {\r\n /**\r\n * @param {AnimationProps} props\r\n */\r\n constructor(props) {\r\n this.props = props;\r\n\r\n const {\r\n start,\r\n end,\r\n velocity,\r\n onUpdate,\r\n onComplete,\r\n onFinish,\r\n dampingRatio,\r\n naturalFrequency\r\n } = props;\r\n\r\n /** @type {() => void} */\r\n this.onFinish = onFinish;\r\n\r\n const easer = new SpringEaser(velocity, dampingRatio, naturalFrequency);\r\n let prevTime = Date.now();\r\n let deltaPosition = start - end;\r\n\r\n const animationLoop = () => {\r\n if (this._raf) {\r\n deltaPosition = easer.easeFrame(deltaPosition, Date.now() - prevTime);\r\n\r\n // Stop the animation if velocity is low and position is close to end\r\n if (Math.abs(deltaPosition) < 1 && Math.abs(easer.velocity) < 50) {\r\n // Finalize the animation\r\n onUpdate(end);\r\n if (onComplete) {\r\n onComplete();\r\n }\r\n this.onFinish();\r\n } else {\r\n prevTime = Date.now();\r\n onUpdate(deltaPosition + end);\r\n this._raf = requestAnimationFrame(animationLoop);\r\n }\r\n }\r\n };\r\n\r\n this._raf = requestAnimationFrame(animationLoop);\r\n }\r\n\r\n // Destroy is called automatically onFinish\r\n destroy() {\r\n if (this._raf >= 0) {\r\n cancelAnimationFrame(this._raf);\r\n }\r\n this._raf = null;\r\n }\r\n}\r\n\r\nexport default SpringAnimation;\r\n","import CSSAnimation from './css-animation.js';\r\nimport SpringAnimation from './spring-animation.js';\r\n\r\n/** @typedef {SpringAnimation | CSSAnimation} Animation */\r\n\r\n/**\r\n * @typedef {Object} AnimationProps\r\n *\r\n * @prop {HTMLElement=} target\r\n *\r\n * @prop {string=} name\r\n *\r\n * @prop {number=} start\r\n * @prop {number=} end\r\n * @prop {number=} duration\r\n * @prop {number=} velocity\r\n * @prop {number=} dampingRatio\r\n * @prop {number=} naturalFrequency\r\n *\r\n * @prop {(end: number) => void} [onUpdate]\r\n * @prop {() => void} [onComplete]\r\n * @prop {() => void} [onFinish]\r\n *\r\n * @prop {string=} transform\r\n * @prop {string=} opacity\r\n * @prop {string=} easing\r\n *\r\n * @prop {boolean=} isPan\r\n * @prop {boolean=} isMainScroll\r\n */\r\n\r\n/**\r\n * Manages animations\r\n */\r\nclass Animations {\r\n constructor() {\r\n /** @type {Animation[]} */\r\n this.activeAnimations = [];\r\n }\r\n\r\n /**\r\n * @param {AnimationProps} props\r\n */\r\n startSpring(props) {\r\n this._start(props, true);\r\n }\r\n\r\n /**\r\n * @param {AnimationProps} props\r\n */\r\n startTransition(props) {\r\n this._start(props);\r\n }\r\n\r\n /**\r\n * @param {AnimationProps} props\r\n * @param {boolean=} isSpring\r\n */\r\n _start(props, isSpring) {\r\n /** @type {Animation} */\r\n let animation;\r\n if (isSpring) {\r\n animation = new SpringAnimation(props);\r\n } else {\r\n animation = new CSSAnimation(props);\r\n }\r\n\r\n this.activeAnimations.push(animation);\r\n animation.onFinish = () => this.stop(animation);\r\n\r\n return animation;\r\n }\r\n\r\n /**\r\n * @param {Animation} animation\r\n */\r\n stop(animation) {\r\n animation.destroy();\r\n const index = this.activeAnimations.indexOf(animation);\r\n if (index > -1) {\r\n this.activeAnimations.splice(index, 1);\r\n }\r\n }\r\n\r\n stopAll() { // _stopAllAnimations\r\n this.activeAnimations.forEach((animation) => {\r\n animation.destroy();\r\n });\r\n this.activeAnimations = [];\r\n }\r\n\r\n /**\r\n * Stop all pan or zoom transitions\r\n */\r\n stopAllPan() {\r\n this.activeAnimations = this.activeAnimations.filter((animation) => {\r\n if (animation.props.isPan) {\r\n animation.destroy();\r\n return false;\r\n }\r\n\r\n return true;\r\n });\r\n }\r\n\r\n stopMainScroll() {\r\n this.activeAnimations = this.activeAnimations.filter((animation) => {\r\n if (animation.props.isMainScroll) {\r\n animation.destroy();\r\n return false;\r\n }\r\n\r\n return true;\r\n });\r\n }\r\n\r\n /**\r\n * Returns true if main scroll transition is running\r\n */\r\n // isMainScrollRunning() {\r\n // return this.activeAnimations.some((animation) => {\r\n // return animation.props.isMainScroll;\r\n // });\r\n // }\r\n\r\n /**\r\n * Returns true if any pan or zoom transition is running\r\n */\r\n isPanRunning() {\r\n return this.activeAnimations.some((animation) => {\r\n return animation.props.isPan;\r\n });\r\n }\r\n}\r\n\r\nexport default Animations;\r\n","/** @typedef {import('./photoswipe.js').default} PhotoSwipe */\r\n\r\n/**\r\n * Handles scroll wheel.\r\n * Can pan and zoom current slide image.\r\n */\r\nclass ScrollWheel {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(pswp) {\r\n this.pswp = pswp;\r\n pswp.events.add(pswp.element, 'wheel', this._onWheel.bind(this));\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {WheelEvent} e\r\n */\r\n _onWheel(e) {\r\n e.preventDefault();\r\n const { currSlide } = this.pswp;\r\n let { deltaX, deltaY } = e;\r\n\r\n if (!currSlide) {\r\n return;\r\n }\r\n\r\n if (this.pswp.dispatch('wheel', { originalEvent: e }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (e.ctrlKey || this.pswp.options.wheelToZoom) {\r\n // zoom\r\n if (currSlide.isZoomable()) {\r\n let zoomFactor = -deltaY;\r\n if (e.deltaMode === 1 /* DOM_DELTA_LINE */) {\r\n zoomFactor *= 0.05;\r\n } else {\r\n zoomFactor *= e.deltaMode ? 1 : 0.002;\r\n }\r\n zoomFactor = 2 ** zoomFactor;\r\n\r\n const destZoomLevel = currSlide.currZoomLevel * zoomFactor;\r\n currSlide.zoomTo(destZoomLevel, {\r\n x: e.clientX,\r\n y: e.clientY\r\n });\r\n }\r\n } else {\r\n // pan\r\n if (currSlide.isPannable()) {\r\n if (e.deltaMode === 1 /* DOM_DELTA_LINE */) {\r\n // 18 - average line height\r\n deltaX *= 18;\r\n deltaY *= 18;\r\n }\r\n\r\n currSlide.panTo(\r\n currSlide.pan.x - deltaX,\r\n currSlide.pan.y - deltaY\r\n );\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport default ScrollWheel;\r\n","import { createElement } from '../util/util.js';\r\n\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n\r\n/**\r\n * @template T\r\n * @typedef {import('../types.js').Methods} Methods\r\n */\r\n\r\n/**\r\n * @typedef {Object} UIElementMarkupProps\r\n * @prop {boolean=} isCustomSVG\r\n * @prop {string} inner\r\n * @prop {string=} outlineID\r\n * @prop {number | string} [size]\r\n */\r\n\r\n/**\r\n * @typedef {Object} UIElementData\r\n * @prop {DefaultUIElements | string} [name]\r\n * @prop {string=} className\r\n * @prop {UIElementMarkup=} html\r\n * @prop {boolean=} isButton\r\n * @prop {keyof HTMLElementTagNameMap} [tagName]\r\n * @prop {string=} title\r\n * @prop {string=} ariaLabel\r\n * @prop {(element: HTMLElement, pswp: PhotoSwipe) => void} [onInit]\r\n * @prop {Methods | ((e: MouseEvent, element: HTMLElement, pswp: PhotoSwipe) => void)} [onClick]\r\n * @prop {'bar' | 'wrapper' | 'root'} [appendTo]\r\n * @prop {number=} order\r\n */\r\n\r\n/** @typedef {'arrowPrev' | 'arrowNext' | 'close' | 'zoom' | 'counter'} DefaultUIElements */\r\n\r\n/** @typedef {string | UIElementMarkupProps} UIElementMarkup */\r\n\r\n/**\r\n * @param {UIElementMarkup} [htmlData]\r\n */\r\nfunction addElementHTML(htmlData) {\r\n if (typeof htmlData === 'string') {\r\n // Allow developers to provide full svg,\r\n // For example:\r\n // \r\n // \r\n // \r\n // \r\n // Can also be any HTML string.\r\n return htmlData;\r\n }\r\n\r\n if (!htmlData || !htmlData.isCustomSVG) {\r\n return '';\r\n }\r\n\r\n const svgData = htmlData;\r\n let out = '';\r\n // replace all %d with size\r\n out = out.split('%d').join(/** @type {string} */ (svgData.size || 32));\r\n\r\n // Icons may contain outline/shadow,\r\n // to make it we \"clone\" base icon shape and add border to it.\r\n // Icon itself and border are styled via CSS.\r\n //\r\n // Property shadowID defines ID of element that should be cloned.\r\n if (svgData.outlineID) {\r\n out += '';\r\n }\r\n\r\n out += svgData.inner;\r\n\r\n out += '';\r\n\r\n return out;\r\n}\r\n\r\nclass UIElement {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n * @param {UIElementData} data\r\n */\r\n constructor(pswp, data) {\r\n const name = data.name || data.className;\r\n let elementHTML = data.html;\r\n\r\n // @ts-expect-error lookup only by `data.name` maybe?\r\n if (pswp.options[name] === false) {\r\n // exit if element is disabled from options\r\n return;\r\n }\r\n\r\n // Allow to override SVG icons from options\r\n // @ts-expect-error lookup only by `data.name` maybe?\r\n if (typeof pswp.options[name + 'SVG'] === 'string') {\r\n // arrowPrevSVG\r\n // arrowNextSVG\r\n // closeSVG\r\n // zoomSVG\r\n // @ts-expect-error lookup only by `data.name` maybe?\r\n elementHTML = pswp.options[name + 'SVG'];\r\n }\r\n\r\n pswp.dispatch('uiElementCreate', { data });\r\n\r\n let className = '';\r\n if (data.isButton) {\r\n className += 'pswp__button ';\r\n className += (data.className || `pswp__button--${data.name}`);\r\n } else {\r\n className += (data.className || `pswp__${data.name}`);\r\n }\r\n\r\n /** @type {HTMLElement} */\r\n let element;\r\n let tagName = data.isButton ? (data.tagName || 'button') : (data.tagName || 'div');\r\n tagName = /** @type {keyof HTMLElementTagNameMap} */ (tagName.toLowerCase());\r\n element = createElement(className, tagName);\r\n\r\n if (data.isButton) {\r\n // create button element\r\n element = createElement(className, tagName);\r\n if (tagName === 'button') {\r\n /** @type {HTMLButtonElement} */ (element).type = 'button';\r\n }\r\n\r\n let { title } = data;\r\n const { ariaLabel } = data;\r\n\r\n // @ts-expect-error lookup only by `data.name` maybe?\r\n if (typeof pswp.options[name + 'Title'] === 'string') {\r\n // @ts-expect-error lookup only by `data.name` maybe?\r\n title = pswp.options[name + 'Title'];\r\n }\r\n\r\n if (title) {\r\n element.title = title;\r\n }\r\n\r\n if (ariaLabel || title) {\r\n /** @type {HTMLElement} */ (element).setAttribute('aria-label', ariaLabel || title);\r\n }\r\n }\r\n\r\n element.innerHTML = addElementHTML(elementHTML);\r\n\r\n if (data.onInit) {\r\n data.onInit(element, pswp);\r\n }\r\n\r\n if (data.onClick) {\r\n element.onclick = (e) => {\r\n if (typeof data.onClick === 'string') {\r\n pswp[data.onClick]();\r\n } else {\r\n data.onClick(e, element, pswp);\r\n }\r\n };\r\n }\r\n\r\n // Top bar is default position\r\n const appendTo = data.appendTo || 'bar';\r\n let container;\r\n if (appendTo === 'bar') {\r\n if (!pswp.topBar) {\r\n pswp.topBar = createElement('pswp__top-bar pswp__hide-on-close', 'div', pswp.scrollWrap);\r\n }\r\n container = pswp.topBar;\r\n } else {\r\n // element outside of top bar gets a secondary class\r\n // that makes element fade out on close\r\n element.classList.add('pswp__hide-on-close');\r\n\r\n if (appendTo === 'wrapper') {\r\n container = pswp.scrollWrap;\r\n } else {\r\n // root element\r\n container = pswp.element;\r\n }\r\n }\r\n\r\n container.appendChild(pswp.applyFilters('uiElement', element, data));\r\n }\r\n}\r\n\r\nexport default UIElement;\r\n","/*\r\n Backward and forward arrow buttons\r\n */\r\n\r\n/** @typedef {import('./ui-element.js').UIElementData} UIElementData */\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n\r\n/**\r\n *\r\n * @param {HTMLElement} element\r\n * @param {PhotoSwipe} pswp\r\n * @param {boolean=} isNextButton\r\n */\r\nfunction initArrowButton(element, pswp, isNextButton) {\r\n element.classList.add('pswp__button--arrow');\r\n pswp.on('change', () => {\r\n if (!pswp.options.loop) {\r\n if (isNextButton) {\r\n /** @type {HTMLButtonElement} */\r\n (element).disabled = !(pswp.currIndex < pswp.getNumItems() - 1);\r\n } else {\r\n /** @type {HTMLButtonElement} */\r\n (element).disabled = !(pswp.currIndex > 0);\r\n }\r\n }\r\n });\r\n}\r\n\r\n/** @type {UIElementData} */\r\nexport const arrowPrev = {\r\n name: 'arrowPrev',\r\n className: 'pswp__button--arrow--prev',\r\n title: 'Previous',\r\n order: 10,\r\n isButton: true,\r\n appendTo: 'wrapper',\r\n html: {\r\n isCustomSVG: true,\r\n size: 60,\r\n inner: '',\r\n outlineID: 'pswp__icn-arrow'\r\n },\r\n onClick: 'prev',\r\n onInit: initArrowButton\r\n};\r\n\r\n/** @type {UIElementData} */\r\nexport const arrowNext = {\r\n name: 'arrowNext',\r\n className: 'pswp__button--arrow--next',\r\n title: 'Next',\r\n order: 11,\r\n isButton: true,\r\n appendTo: 'wrapper',\r\n html: {\r\n isCustomSVG: true,\r\n size: 60,\r\n inner: '',\r\n outlineID: 'pswp__icn-arrow'\r\n },\r\n onClick: 'next',\r\n onInit: (el, pswp) => {\r\n initArrowButton(el, pswp, true);\r\n }\r\n};\r\n","/** @type {import('./ui-element.js').UIElementData} UIElementData */\r\nconst closeButton = {\r\n name: 'close',\r\n title: 'Close',\r\n order: 20,\r\n isButton: true,\r\n html: {\r\n isCustomSVG: true,\r\n inner: '',\r\n outlineID: 'pswp__icn-close'\r\n },\r\n onClick: 'close'\r\n};\r\n\r\nexport default closeButton;\r\n","/** @type {import('./ui-element.js').UIElementData} UIElementData */\r\nconst zoomButton = {\r\n name: 'zoom',\r\n title: 'Zoom',\r\n order: 10,\r\n isButton: true,\r\n html: {\r\n isCustomSVG: true,\r\n // eslint-disable-next-line max-len\r\n inner: ''\r\n + ''\r\n + '',\r\n outlineID: 'pswp__icn-zoom'\r\n },\r\n onClick: 'toggleZoom'\r\n};\r\n\r\nexport default zoomButton;\r\n","/** @type {import('./ui-element.js').UIElementData} UIElementData */\r\nexport const loadingIndicator = {\r\n name: 'preloader',\r\n appendTo: 'bar',\r\n order: 7,\r\n html: {\r\n isCustomSVG: true,\r\n // eslint-disable-next-line max-len\r\n inner: '',\r\n outlineID: 'pswp__icn-loading'\r\n },\r\n onInit: (indicatorElement, pswp) => {\r\n /** @type {boolean} */\r\n let isVisible;\r\n /** @type {NodeJS.Timeout} */\r\n let delayTimeout;\r\n\r\n /**\r\n * @param {string} className\r\n * @param {boolean} add\r\n */\r\n const toggleIndicatorClass = (className, add) => {\r\n indicatorElement.classList[add ? 'add' : 'remove']('pswp__preloader--' + className);\r\n };\r\n\r\n /**\r\n * @param {boolean} visible\r\n */\r\n const setIndicatorVisibility = (visible) => {\r\n if (isVisible !== visible) {\r\n isVisible = visible;\r\n toggleIndicatorClass('active', visible);\r\n }\r\n };\r\n\r\n const updatePreloaderVisibility = () => {\r\n if (!pswp.currSlide.content.isLoading()) {\r\n setIndicatorVisibility(false);\r\n if (delayTimeout) {\r\n clearTimeout(delayTimeout);\r\n delayTimeout = null;\r\n }\r\n return;\r\n }\r\n\r\n if (!delayTimeout) {\r\n // display loading indicator with delay\r\n delayTimeout = setTimeout(() => {\r\n setIndicatorVisibility(pswp.currSlide.content.isLoading());\r\n delayTimeout = null;\r\n }, pswp.options.preloaderDelay);\r\n }\r\n };\r\n\r\n pswp.on('change', updatePreloaderVisibility);\r\n\r\n pswp.on('loadComplete', (e) => {\r\n if (pswp.currSlide === e.slide) {\r\n updatePreloaderVisibility();\r\n }\r\n });\r\n\r\n // expose the method\r\n pswp.ui.updatePreloaderVisibility = updatePreloaderVisibility;\r\n }\r\n};\r\n","/** @type {import('./ui-element.js').UIElementData} UIElementData */\r\nexport const counterIndicator = {\r\n name: 'counter',\r\n order: 5,\r\n onInit: (counterElement, pswp) => {\r\n pswp.on('change', () => {\r\n counterElement.innerText = (pswp.currIndex + 1)\r\n + pswp.options.indexIndicatorSep\r\n + pswp.getNumItems();\r\n });\r\n }\r\n};\r\n","import UIElement from './ui-element.js';\r\nimport { arrowPrev, arrowNext } from './button-arrow.js';\r\nimport closeButton from './button-close.js';\r\nimport zoomButton from './button-zoom.js';\r\nimport { loadingIndicator } from './loading-indicator.js';\r\nimport { counterIndicator } from './counter-indicator.js';\r\n\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('./ui-element.js').UIElementData} UIElementData */\r\n\r\n/**\r\n * Set special class on element when image is zoomed.\r\n *\r\n * By default it is used to adjust\r\n * zoom icon and zoom cursor via CSS.\r\n *\r\n * @param {HTMLElement} el\r\n * @param {boolean} isZoomedIn\r\n */\r\nfunction setZoomedIn(el, isZoomedIn) {\r\n el.classList[isZoomedIn ? 'add' : 'remove']('pswp--zoomed-in');\r\n}\r\n\r\nclass UI {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(pswp) {\r\n this.pswp = pswp;\r\n\r\n /** @type {() => void} */\r\n this.updatePreloaderVisibility = undefined;\r\n\r\n /** @type {number} */\r\n this._lastUpdatedZoomLevel = undefined;\r\n }\r\n\r\n init() {\r\n const { pswp } = this;\r\n this.isRegistered = false;\r\n /** @type {UIElementData[]} */\r\n this.uiElementsData = [\r\n closeButton,\r\n arrowPrev,\r\n arrowNext,\r\n zoomButton,\r\n loadingIndicator,\r\n counterIndicator\r\n ];\r\n\r\n pswp.dispatch('uiRegister');\r\n\r\n // sort by order\r\n this.uiElementsData.sort((a, b) => {\r\n // default order is 0\r\n return (a.order || 0) - (b.order || 0);\r\n });\r\n\r\n /** @type {(UIElement | UIElementData)[]} */\r\n this.items = [];\r\n\r\n this.isRegistered = true;\r\n this.uiElementsData.forEach((uiElementData) => {\r\n this.registerElement(uiElementData);\r\n });\r\n\r\n pswp.on('change', () => {\r\n pswp.element.classList[pswp.getNumItems() === 1 ? 'add' : 'remove']('pswp--one-slide');\r\n });\r\n\r\n pswp.on('zoomPanUpdate', () => this._onZoomPanUpdate());\r\n }\r\n\r\n /**\r\n * @param {UIElementData} elementData\r\n */\r\n registerElement(elementData) {\r\n if (this.isRegistered) {\r\n this.items.push(\r\n new UIElement(this.pswp, elementData)\r\n );\r\n } else {\r\n this.uiElementsData.push(elementData);\r\n }\r\n }\r\n\r\n /**\r\n * Fired each time zoom or pan position is changed.\r\n * Update classes that control visibility of zoom button and cursor icon.\r\n */\r\n _onZoomPanUpdate() {\r\n const { template, currSlide, options } = this.pswp;\r\n let { currZoomLevel } = currSlide;\r\n\r\n if (this.pswp.opener.isClosing) {\r\n return;\r\n }\r\n\r\n // if not open yet - check against initial zoom level\r\n if (!this.pswp.opener.isOpen) {\r\n currZoomLevel = currSlide.zoomLevels.initial;\r\n }\r\n\r\n if (currZoomLevel === this._lastUpdatedZoomLevel) {\r\n return;\r\n }\r\n this._lastUpdatedZoomLevel = currZoomLevel;\r\n\r\n const currZoomLevelDiff = currSlide.zoomLevels.initial - currSlide.zoomLevels.secondary;\r\n\r\n // Initial and secondary zoom levels are almost equal\r\n if (Math.abs(currZoomLevelDiff) < 0.01 || !currSlide.isZoomable()) {\r\n // disable zoom\r\n setZoomedIn(template, false);\r\n template.classList.remove('pswp--zoom-allowed');\r\n return;\r\n }\r\n\r\n template.classList.add('pswp--zoom-allowed');\r\n\r\n const potentialZoomLevel = currZoomLevel === currSlide.zoomLevels.initial\r\n ? currSlide.zoomLevels.secondary : currSlide.zoomLevels.initial;\r\n\r\n setZoomedIn(template, potentialZoomLevel <= currZoomLevel);\r\n\r\n if (options.imageClickAction === 'zoom'\r\n || options.imageClickAction === 'zoom-or-close') {\r\n template.classList.add('pswp--click-to-zoom');\r\n }\r\n }\r\n}\r\n\r\nexport default UI;\r\n","/** @typedef {import('../lightbox/lightbox.js').default} PhotoSwipeLightbox */\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('../photoswipe.js').PhotoSwipeOptions} PhotoSwipeOptions */\r\n/** @typedef {import('../photoswipe.js').DataSource} DataSource */\r\n/** @typedef {import('../ui/ui-element.js').UIElementData} UIElementData */\r\n/** @typedef {import('../slide/content.js').default} ContentDefault */\r\n/** @typedef {import('../slide/slide.js').default} Slide */\r\n/** @typedef {import('../slide/slide.js').SlideData} SlideData */\r\n/** @typedef {import('../slide/zoom-level.js').default} ZoomLevel */\r\n/** @typedef {import('../slide/get-thumb-bounds.js').Bounds} Bounds */\r\n\r\n/**\r\n * Allow adding an arbitrary props to the Content\r\n * https://photoswipe.com/custom-content/#using-webp-image-format\r\n * @typedef {ContentDefault & Record} Content\r\n */\r\n/** @typedef {{ x?: number; y?: number }} Point */\r\n\r\n/**\r\n * @typedef {Object} PhotoSwipeEventsMap https://photoswipe.com/events/\r\n *\r\n *\r\n * https://photoswipe.com/adding-ui-elements/\r\n *\r\n * @prop {undefined} uiRegister\r\n * @prop {{ data: UIElementData }} uiElementCreate\r\n *\r\n *\r\n * https://photoswipe.com/events/#initialization-events\r\n *\r\n * @prop {undefined} beforeOpen\r\n * @prop {undefined} firstUpdate\r\n * @prop {undefined} initialLayout\r\n * @prop {undefined} change\r\n * @prop {undefined} afterInit\r\n * @prop {undefined} bindEvents\r\n *\r\n *\r\n * https://photoswipe.com/events/#opening-or-closing-transition-events\r\n *\r\n * @prop {undefined} openingAnimationStart\r\n * @prop {undefined} openingAnimationEnd\r\n * @prop {undefined} closingAnimationStart\r\n * @prop {undefined} closingAnimationEnd\r\n *\r\n *\r\n * https://photoswipe.com/events/#closing-events\r\n *\r\n * @prop {undefined} close\r\n * @prop {undefined} destroy\r\n *\r\n *\r\n * https://photoswipe.com/events/#pointer-and-gesture-events\r\n *\r\n * @prop {{ originalEvent: PointerEvent }} pointerDown\r\n * @prop {{ originalEvent: PointerEvent }} pointerMove\r\n * @prop {{ originalEvent: PointerEvent }} pointerUp\r\n * @prop {{ bgOpacity: number }} pinchClose can be default prevented\r\n * @prop {{ panY: number }} verticalDrag can be default prevented\r\n *\r\n *\r\n * https://photoswipe.com/events/#slide-content-events\r\n *\r\n * @prop {{ content: Content }} contentInit\r\n * @prop {{ content: Content; isLazy: boolean }} contentLoad can be default prevented\r\n * @prop {{ content: Content; isLazy: boolean }} contentLoadImage can be default prevented\r\n * @prop {{ content: Content; slide: Slide; isError?: boolean }} loadComplete\r\n * @prop {{ content: Content; slide: Slide }} loadError\r\n * @prop {{ content: Content; width: number; height: number }} contentResize can be default prevented\r\n * @prop {{ content: Content; width: number; height: number; slide: Slide }} imageSizeChange\r\n * @prop {{ content: Content }} contentLazyLoad can be default prevented\r\n * @prop {{ content: Content }} contentAppend can be default prevented\r\n * @prop {{ content: Content }} contentActivate can be default prevented\r\n * @prop {{ content: Content }} contentDeactivate can be default prevented\r\n * @prop {{ content: Content }} contentRemove can be default prevented\r\n * @prop {{ content: Content }} contentDestroy can be default prevented\r\n *\r\n *\r\n * undocumented\r\n *\r\n * @prop {{ point: Point; originalEvent: PointerEvent }} imageClickAction can be default prevented\r\n * @prop {{ point: Point; originalEvent: PointerEvent }} bgClickAction can be default prevented\r\n * @prop {{ point: Point; originalEvent: PointerEvent }} tapAction can be default prevented\r\n * @prop {{ point: Point; originalEvent: PointerEvent }} doubleTapAction can be default prevented\r\n *\r\n * @prop {{ originalEvent: KeyboardEvent }} keydown can be default prevented\r\n * @prop {{ x: number; dragging: boolean }} moveMainScroll\r\n * @prop {{ slide: Slide }} firstZoomPan\r\n * @prop {{ slide: Slide, data: SlideData, index: number }} gettingData\r\n * @prop {undefined} beforeResize\r\n * @prop {undefined} resize\r\n * @prop {undefined} viewportSize\r\n * @prop {undefined} updateScrollOffset\r\n * @prop {{ slide: Slide }} slideInit\r\n * @prop {{ slide: Slide }} afterSetContent\r\n * @prop {{ slide: Slide }} slideLoad\r\n * @prop {{ slide: Slide }} appendHeavy can be default prevented\r\n * @prop {{ slide: Slide }} appendHeavyContent\r\n * @prop {{ slide: Slide }} slideActivate\r\n * @prop {{ slide: Slide }} slideDeactivate\r\n * @prop {{ slide: Slide }} slideDestroy\r\n * @prop {{ destZoomLevel: number, centerPoint: Point, transitionDuration: number | false }} beforeZoomTo\r\n * @prop {{ slide: Slide }} zoomPanUpdate\r\n * @prop {{ slide: Slide }} initialZoomPan\r\n * @prop {{ slide: Slide }} calcSlideSize\r\n * @prop {undefined} resolutionChanged\r\n * @prop {{ originalEvent: WheelEvent }} wheel can be default prevented\r\n * @prop {{ content: Content }} contentAppendImage can be default prevented\r\n * @prop {{ index: number; itemData: SlideData }} lazyLoadSlide can be default prevented\r\n * @prop {undefined} lazyLoad\r\n * @prop {{ slide: Slide }} calcBounds\r\n * @prop {{ zoomLevels: ZoomLevel, slideData: SlideData }} zoomLevelsUpdate\r\n *\r\n *\r\n * legacy\r\n *\r\n * @prop {undefined} init\r\n * @prop {undefined} initialZoomIn\r\n * @prop {undefined} initialZoomOut\r\n * @prop {undefined} initialZoomInEnd\r\n * @prop {undefined} initialZoomOutEnd\r\n * @prop {{ dataSource: DataSource, numItems: number }} numItems\r\n * @prop {{ itemData: SlideData; index: number }} itemData\r\n * @prop {{ index: number, itemData: SlideData, instance: PhotoSwipe }} thumbBounds\r\n */\r\n\r\n/**\r\n * @typedef {Object} PhotoSwipeFiltersMap https://photoswipe.com/filters/\r\n *\r\n * @prop {(numItems: number, dataSource: DataSource) => number} numItems\r\n * Modify the total amount of slides. Example on Data sources page.\r\n * https://photoswipe.com/filters/#numitems\r\n *\r\n * @prop {(itemData: SlideData, index: number) => SlideData} itemData\r\n * Modify slide item data. Example on Data sources page.\r\n * https://photoswipe.com/filters/#itemdata\r\n *\r\n * @prop {(itemData: SlideData, element: HTMLElement, linkEl: HTMLAnchorElement) => SlideData} domItemData\r\n * Modify item data when it's parsed from DOM element. Example on Data sources page.\r\n * https://photoswipe.com/filters/#domitemdata\r\n *\r\n * @prop {(clickedIndex: number, e: MouseEvent, instance: PhotoSwipeLightbox) => number} clickedIndex\r\n * Modify clicked gallery item index.\r\n * https://photoswipe.com/filters/#clickedindex\r\n *\r\n * @prop {(placeholderSrc: string | false, content: Content) => string | false} placeholderSrc\r\n * Modify placeholder image source.\r\n * https://photoswipe.com/filters/#placeholdersrc\r\n *\r\n * @prop {(isContentLoading: boolean, content: Content) => boolean} isContentLoading\r\n * Modify if the content is currently loading.\r\n * https://photoswipe.com/filters/#iscontentloading\r\n *\r\n * @prop {(isContentZoomable: boolean, content: Content) => boolean} isContentZoomable\r\n * Modify if the content can be zoomed.\r\n * https://photoswipe.com/filters/#iscontentzoomable\r\n *\r\n * @prop {(useContentPlaceholder: boolean, content: Content) => boolean} useContentPlaceholder\r\n * Modify if the placeholder should be used for the content.\r\n * https://photoswipe.com/filters/#usecontentplaceholder\r\n *\r\n * @prop {(isKeepingPlaceholder: boolean, content: Content) => boolean} isKeepingPlaceholder\r\n * Modify if the placeholder should be kept after the content is loaded.\r\n * https://photoswipe.com/filters/#iskeepingplaceholder\r\n *\r\n *\r\n * @prop {(contentErrorElement: HTMLElement, content: Content) => HTMLElement} contentErrorElement\r\n * Modify an element when the content has error state (for example, if image cannot be loaded).\r\n * https://photoswipe.com/filters/#contenterrorelement\r\n *\r\n * @prop {(element: HTMLElement, data: UIElementData) => HTMLElement} uiElement\r\n * Modify a UI element that's being created.\r\n * https://photoswipe.com/filters/#uielement\r\n *\r\n * @prop {(thumbnail: HTMLElement, itemData: SlideData, index: number) => HTMLElement} thumbEl\r\n * Modify the thubmnail element from which opening zoom animation starts or ends.\r\n * https://photoswipe.com/filters/#thumbel\r\n *\r\n * @prop {(thumbBounds: Bounds, itemData: SlideData, index: number) => Bounds} thumbBounds\r\n * Modify the thubmnail bounds from which opening zoom animation starts or ends.\r\n * https://photoswipe.com/filters/#thumbbounds\r\n *\r\n * @prop {(srcsetSizesWidth: number, content: Content) => number} srcsetSizesWidth\r\n *\r\n */\r\n\r\n/**\r\n * @template {keyof PhotoSwipeFiltersMap} T\r\n * @typedef {{ fn: PhotoSwipeFiltersMap[T], priority: number }} Filter\r\n */\r\n\r\n/**\r\n * @template {keyof PhotoSwipeEventsMap} T\r\n * @typedef {PhotoSwipeEventsMap[T] extends undefined ? PhotoSwipeEvent : PhotoSwipeEvent & PhotoSwipeEventsMap[T]} AugmentedEvent\r\n */\r\n\r\n/**\r\n * @template {keyof PhotoSwipeEventsMap} T\r\n * @typedef {(event: AugmentedEvent) => void} EventCallback\r\n */\r\n\r\n/**\r\n * Base PhotoSwipe event object\r\n *\r\n * @template {keyof PhotoSwipeEventsMap} T\r\n */\r\nclass PhotoSwipeEvent {\r\n /**\r\n * @param {T} type\r\n * @param {PhotoSwipeEventsMap[T]} [details]\r\n */\r\n constructor(type, details) {\r\n this.type = type;\r\n if (details) {\r\n Object.assign(this, details);\r\n }\r\n }\r\n\r\n preventDefault() {\r\n this.defaultPrevented = true;\r\n }\r\n}\r\n\r\n/**\r\n * PhotoSwipe base class that can listen and dispatch for events.\r\n * Shared by PhotoSwipe Core and PhotoSwipe Lightbox, extended by base.js\r\n */\r\nclass Eventable {\r\n constructor() {\r\n /**\r\n * @type {{ [T in keyof PhotoSwipeEventsMap]?: ((event: AugmentedEvent) => void)[] }}\r\n */\r\n this._listeners = {};\r\n\r\n /**\r\n * @type {{ [T in keyof PhotoSwipeFiltersMap]?: Filter[] }}\r\n */\r\n this._filters = {};\r\n\r\n /** @type {PhotoSwipe=} */\r\n this.pswp = undefined;\r\n\r\n /** @type {PhotoSwipeOptions} */\r\n this.options = undefined;\r\n }\r\n\r\n /**\r\n * @template {keyof PhotoSwipeFiltersMap} T\r\n * @param {T} name\r\n * @param {PhotoSwipeFiltersMap[T]} fn\r\n * @param {number} priority\r\n */\r\n addFilter(name, fn, priority = 100) {\r\n if (!this._filters[name]) {\r\n this._filters[name] = [];\r\n }\r\n\r\n this._filters[name].push({ fn, priority });\r\n this._filters[name].sort((f1, f2) => f1.priority - f2.priority);\r\n\r\n if (this.pswp) {\r\n this.pswp.addFilter(name, fn, priority);\r\n }\r\n }\r\n\r\n /**\r\n * @template {keyof PhotoSwipeFiltersMap} T\r\n * @param {T} name\r\n * @param {PhotoSwipeFiltersMap[T]} fn\r\n */\r\n removeFilter(name, fn) {\r\n if (this._filters[name]) {\r\n // @ts-expect-error\r\n this._filters[name] = this._filters[name].filter(filter => (filter.fn !== fn));\r\n }\r\n\r\n if (this.pswp) {\r\n this.pswp.removeFilter(name, fn);\r\n }\r\n }\r\n\r\n /**\r\n * @template {keyof PhotoSwipeFiltersMap} T\r\n * @param {T} name\r\n * @param {Parameters} args\r\n * @returns {Parameters[0]}\r\n */\r\n applyFilters(name, ...args) {\r\n if (this._filters[name]) {\r\n this._filters[name].forEach((filter) => {\r\n // @ts-expect-error\r\n args[0] = filter.fn.apply(this, args);\r\n });\r\n }\r\n return args[0];\r\n }\r\n\r\n /**\r\n * @template {keyof PhotoSwipeEventsMap} T\r\n * @param {T} name\r\n * @param {EventCallback} fn\r\n */\r\n on(name, fn) {\r\n if (!this._listeners[name]) {\r\n this._listeners[name] = [];\r\n }\r\n this._listeners[name].push(fn);\r\n\r\n // When binding events to lightbox,\r\n // also bind events to PhotoSwipe Core,\r\n // if it's open.\r\n if (this.pswp) {\r\n this.pswp.on(name, fn);\r\n }\r\n }\r\n\r\n /**\r\n * @template {keyof PhotoSwipeEventsMap} T\r\n * @param {T} name\r\n * @param {EventCallback} fn\r\n */\r\n off(name, fn) {\r\n if (this._listeners[name]) {\r\n // @ts-expect-error\r\n this._listeners[name] = this._listeners[name].filter(listener => (fn !== listener));\r\n }\r\n\r\n if (this.pswp) {\r\n this.pswp.off(name, fn);\r\n }\r\n }\r\n\r\n /**\r\n * @template {keyof PhotoSwipeEventsMap} T\r\n * @param {T} name\r\n * @param {PhotoSwipeEventsMap[T]} [details]\r\n * @returns {AugmentedEvent}\r\n */\r\n dispatch(name, details) {\r\n if (this.pswp) {\r\n return this.pswp.dispatch(name, details);\r\n }\r\n\r\n const event = /** @type {AugmentedEvent} */ (new PhotoSwipeEvent(name, details));\r\n\r\n if (!this._listeners) {\r\n return event;\r\n }\r\n\r\n if (this._listeners[name]) {\r\n this._listeners[name].forEach((listener) => {\r\n listener.call(this, event);\r\n });\r\n }\r\n\r\n return event;\r\n }\r\n}\r\n\r\nexport default Eventable;\r\n","import { createElement, setWidthHeight, toTransformString } from '../util/util.js';\r\n\r\nclass Placeholder {\r\n /**\r\n * @param {string | false} imageSrc\r\n * @param {HTMLElement} container\r\n */\r\n constructor(imageSrc, container) {\r\n // Create placeholder\r\n // (stretched thumbnail or simple div behind the main image)\r\n this.element = createElement(\r\n 'pswp__img pswp__img--placeholder',\r\n imageSrc ? 'img' : '',\r\n container\r\n );\r\n\r\n if (imageSrc) {\r\n /** @type {HTMLImageElement} */\r\n (this.element).decoding = 'async';\r\n /** @type {HTMLImageElement} */\r\n (this.element).alt = '';\r\n /** @type {HTMLImageElement} */\r\n (this.element).src = imageSrc;\r\n this.element.setAttribute('role', 'presentation');\r\n }\r\n\r\n this.element.setAttribute('aria-hiden', 'true');\r\n }\r\n\r\n /**\r\n * @param {number} width\r\n * @param {number} height\r\n */\r\n setDisplayedSize(width, height) {\r\n if (!this.element) {\r\n return;\r\n }\r\n\r\n if (this.element.tagName === 'IMG') {\r\n // Use transform scale() to modify img placeholder size\r\n // (instead of changing width/height directly).\r\n // This helps with performance, specifically in iOS15 Safari.\r\n setWidthHeight(this.element, 250, 'auto');\r\n this.element.style.transformOrigin = '0 0';\r\n this.element.style.transform = toTransformString(0, 0, width / 250);\r\n } else {\r\n setWidthHeight(this.element, width, height);\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.element.parentNode) {\r\n this.element.remove();\r\n }\r\n this.element = null;\r\n }\r\n}\r\n\r\nexport default Placeholder;\r\n","import { createElement, isSafari, LOAD_STATE, setWidthHeight } from '../util/util.js';\r\nimport Placeholder from './placeholder.js';\r\n\r\n/** @typedef {import('./slide.js').default} Slide */\r\n/** @typedef {import('./slide.js').SlideData} SlideData */\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('../util/util.js').LoadState} LoadState */\r\n\r\nclass Content {\r\n /**\r\n * @param {SlideData} itemData Slide data\r\n * @param {PhotoSwipe} instance PhotoSwipe or PhotoSwipeLightbox instance\r\n * @param {number} index\r\n */\r\n constructor(itemData, instance, index) {\r\n this.instance = instance;\r\n this.data = itemData;\r\n this.index = index;\r\n\r\n /** @type {HTMLImageElement | HTMLDivElement} */\r\n this.element = undefined;\r\n\r\n this.displayedImageWidth = 0;\r\n this.displayedImageHeight = 0;\r\n\r\n this.width = Number(this.data.w) || Number(this.data.width) || 0;\r\n this.height = Number(this.data.h) || Number(this.data.height) || 0;\r\n\r\n this.isAttached = false;\r\n this.hasSlide = false;\r\n /** @type {LoadState} */\r\n this.state = LOAD_STATE.IDLE;\r\n\r\n if (this.data.type) {\r\n this.type = this.data.type;\r\n } else if (this.data.src) {\r\n this.type = 'image';\r\n } else {\r\n this.type = 'html';\r\n }\r\n\r\n this.instance.dispatch('contentInit', { content: this });\r\n }\r\n\r\n removePlaceholder() {\r\n if (this.placeholder && !this.keepPlaceholder()) {\r\n // With delay, as image might be loaded, but not rendered\r\n setTimeout(() => {\r\n if (this.placeholder) {\r\n this.placeholder.destroy();\r\n this.placeholder = null;\r\n }\r\n }, 1000);\r\n }\r\n }\r\n\r\n /**\r\n * Preload content\r\n *\r\n * @param {boolean=} isLazy\r\n * @param {boolean=} reload\r\n */\r\n load(isLazy, reload) {\r\n if (this.slide && this.usePlaceholder()) {\r\n if (!this.placeholder) {\r\n const placeholderSrc = this.instance.applyFilters(\r\n 'placeholderSrc',\r\n // use image-based placeholder only for the first slide,\r\n // as rendering (even small stretched thumbnail) is an expensive operation\r\n (this.data.msrc && this.slide.isFirstSlide) ? this.data.msrc : false,\r\n this\r\n );\r\n this.placeholder = new Placeholder(\r\n placeholderSrc,\r\n this.slide.container\r\n );\r\n } else {\r\n const placeholderEl = this.placeholder.element;\r\n // Add placeholder to DOM if it was already created\r\n if (placeholderEl && !placeholderEl.parentElement) {\r\n this.slide.container.prepend(placeholderEl);\r\n }\r\n }\r\n }\r\n\r\n if (this.element && !reload) {\r\n return;\r\n }\r\n\r\n if (this.instance.dispatch('contentLoad', { content: this, isLazy }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (this.isImageContent()) {\r\n this.element = createElement('pswp__img', 'img');\r\n // Start loading only after width is defined, as sizes might depend on it.\r\n // Due to Safari feature, we must define sizes before srcset.\r\n if (this.displayedImageWidth) {\r\n this.loadImage(isLazy);\r\n }\r\n } else {\r\n this.element = createElement('pswp__content');\r\n this.element.innerHTML = this.data.html || '';\r\n }\r\n\r\n if (reload && this.slide) {\r\n this.slide.updateContentSize(true);\r\n }\r\n }\r\n\r\n /**\r\n * Preload image\r\n *\r\n * @param {boolean} isLazy\r\n */\r\n loadImage(isLazy) {\r\n const imageElement = /** @type HTMLImageElement */ (this.element);\r\n\r\n if (this.instance.dispatch('contentLoadImage', { content: this, isLazy }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n this.updateSrcsetSizes();\r\n\r\n if (this.data.srcset) {\r\n imageElement.srcset = this.data.srcset;\r\n }\r\n\r\n imageElement.src = this.data.src;\r\n\r\n imageElement.alt = this.data.alt || '';\r\n\r\n this.state = LOAD_STATE.LOADING;\r\n\r\n if (imageElement.complete) {\r\n this.onLoaded();\r\n } else {\r\n imageElement.onload = () => {\r\n this.onLoaded();\r\n };\r\n\r\n imageElement.onerror = () => {\r\n this.onError();\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Assign slide to content\r\n *\r\n * @param {Slide} slide\r\n */\r\n setSlide(slide) {\r\n this.slide = slide;\r\n this.hasSlide = true;\r\n this.instance = slide.pswp;\r\n\r\n // todo: do we need to unset slide?\r\n }\r\n\r\n /**\r\n * Content load success handler\r\n */\r\n onLoaded() {\r\n this.state = LOAD_STATE.LOADED;\r\n\r\n if (this.slide) {\r\n this.instance.dispatch('loadComplete', { slide: this.slide, content: this });\r\n\r\n // if content is reloaded\r\n if (this.slide.isActive\r\n && this.slide.heavyAppended\r\n && !this.element.parentNode) {\r\n this.append();\r\n this.slide.updateContentSize(true);\r\n }\r\n\r\n if (this.state === LOAD_STATE.LOADED || this.state === LOAD_STATE.ERROR) {\r\n this.removePlaceholder();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Content load error handler\r\n */\r\n onError() {\r\n this.state = LOAD_STATE.ERROR;\r\n\r\n if (this.slide) {\r\n this.displayError();\r\n this.instance.dispatch('loadComplete', { slide: this.slide, isError: true, content: this });\r\n this.instance.dispatch('loadError', { slide: this.slide, content: this });\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Boolean} If the content is currently loading\r\n */\r\n isLoading() {\r\n return this.instance.applyFilters(\r\n 'isContentLoading',\r\n this.state === LOAD_STATE.LOADING,\r\n this\r\n );\r\n }\r\n\r\n isError() {\r\n return this.state === LOAD_STATE.ERROR;\r\n }\r\n\r\n /**\r\n * @returns {boolean} If the content is image\r\n */\r\n isImageContent() {\r\n return this.type === 'image';\r\n }\r\n\r\n /**\r\n * Update content size\r\n *\r\n * @param {Number} width\r\n * @param {Number} height\r\n */\r\n setDisplayedSize(width, height) {\r\n if (!this.element) {\r\n return;\r\n }\r\n\r\n if (this.placeholder) {\r\n this.placeholder.setDisplayedSize(width, height);\r\n }\r\n\r\n // eslint-disable-next-line max-len\r\n if (this.instance.dispatch('contentResize', { content: this, width, height }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n setWidthHeight(this.element, width, height);\r\n\r\n if (this.isImageContent() && !this.isError()) {\r\n const isInitialSizeUpdate = (!this.displayedImageWidth && width);\r\n\r\n this.displayedImageWidth = width;\r\n this.displayedImageHeight = height;\r\n\r\n if (isInitialSizeUpdate) {\r\n this.loadImage(false);\r\n } else {\r\n this.updateSrcsetSizes();\r\n }\r\n\r\n if (this.slide) {\r\n // eslint-disable-next-line max-len\r\n this.instance.dispatch('imageSizeChange', { slide: this.slide, width, height, content: this });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @returns {boolean} If the content can be zoomed\r\n */\r\n isZoomable() {\r\n return this.instance.applyFilters(\r\n 'isContentZoomable',\r\n this.isImageContent() && (this.state !== LOAD_STATE.ERROR),\r\n this\r\n );\r\n }\r\n\r\n /**\r\n * Update image srcset sizes attribute based on width and height\r\n */\r\n updateSrcsetSizes() {\r\n // Handle srcset sizes attribute.\r\n //\r\n // Never lower quality, if it was increased previously.\r\n // Chrome does this automatically, Firefox and Safari do not,\r\n // so we store largest used size in dataset.\r\n // Handle srcset sizes attribute.\r\n //\r\n // Never lower quality, if it was increased previously.\r\n // Chrome does this automatically, Firefox and Safari do not,\r\n // so we store largest used size in dataset.\r\n if (this.data.srcset) {\r\n const image = /** @type HTMLImageElement */ (this.element);\r\n const sizesWidth = this.instance.applyFilters(\r\n 'srcsetSizesWidth',\r\n this.displayedImageWidth,\r\n this\r\n );\r\n\r\n if (!image.dataset.largestUsedSize\r\n || sizesWidth > parseInt(image.dataset.largestUsedSize, 10)) {\r\n image.sizes = sizesWidth + 'px';\r\n image.dataset.largestUsedSize = String(sizesWidth);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @returns {boolean} If content should use a placeholder (from msrc by default)\r\n */\r\n usePlaceholder() {\r\n return this.instance.applyFilters(\r\n 'useContentPlaceholder',\r\n this.isImageContent(),\r\n this\r\n );\r\n }\r\n\r\n /**\r\n * Preload content with lazy-loading param\r\n */\r\n lazyLoad() {\r\n if (this.instance.dispatch('contentLazyLoad', { content: this }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n this.load(true);\r\n }\r\n\r\n /**\r\n * @returns {boolean} If placeholder should be kept after content is loaded\r\n */\r\n keepPlaceholder() {\r\n return this.instance.applyFilters(\r\n 'isKeepingPlaceholder',\r\n this.isLoading(),\r\n this\r\n );\r\n }\r\n\r\n /**\r\n * Destroy the content\r\n */\r\n destroy() {\r\n this.hasSlide = false;\r\n this.slide = null;\r\n\r\n if (this.instance.dispatch('contentDestroy', { content: this }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n this.remove();\r\n\r\n if (this.placeholder) {\r\n this.placeholder.destroy();\r\n this.placeholder = null;\r\n }\r\n\r\n if (this.isImageContent() && this.element) {\r\n this.element.onload = null;\r\n this.element.onerror = null;\r\n this.element = null;\r\n }\r\n }\r\n\r\n /**\r\n * Display error message\r\n */\r\n displayError() {\r\n if (this.slide) {\r\n /** @type {HTMLElement} */\r\n let errorMsgEl = createElement('pswp__error-msg');\r\n errorMsgEl.innerText = this.instance.options.errorMsg;\r\n errorMsgEl = this.instance.applyFilters(\r\n 'contentErrorElement',\r\n errorMsgEl,\r\n this\r\n );\r\n this.element = createElement('pswp__content pswp__error-msg-container');\r\n this.element.appendChild(errorMsgEl);\r\n this.slide.container.innerText = '';\r\n this.slide.container.appendChild(this.element);\r\n this.slide.updateContentSize(true);\r\n this.removePlaceholder();\r\n }\r\n }\r\n\r\n /**\r\n * Append the content\r\n */\r\n append() {\r\n if (this.isAttached) {\r\n return;\r\n }\r\n\r\n this.isAttached = true;\r\n\r\n if (this.state === LOAD_STATE.ERROR) {\r\n this.displayError();\r\n return;\r\n }\r\n\r\n if (this.instance.dispatch('contentAppend', { content: this }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n const supportsDecode = ('decode' in this.element);\r\n\r\n if (this.isImageContent()) {\r\n // Use decode() on nearby slides\r\n //\r\n // Nearby slide images are in DOM and not hidden via display:none.\r\n // However, they are placed offscreen (to the left and right side).\r\n //\r\n // Some browsers do not composite the image until it's actually visible,\r\n // using decode() helps.\r\n //\r\n // You might ask \"why dont you just decode() and then append all images\",\r\n // that's because I want to show image before it's fully loaded,\r\n // as browser can render parts of image while it is loading.\r\n // We do not do this in Safari due to partial loading bug.\r\n if (supportsDecode && this.slide && (!this.slide.isActive || isSafari())) {\r\n this.isDecoding = true;\r\n // purposefully using finally instead of then,\r\n // as if srcset sizes changes dynamically - it may cause decode error\r\n /** @type {HTMLImageElement} */\r\n (this.element).decode().finally(() => {\r\n this.isDecoding = false;\r\n this.appendImage();\r\n });\r\n } else {\r\n this.appendImage();\r\n }\r\n } else if (this.element && !this.element.parentNode) {\r\n this.slide.container.appendChild(this.element);\r\n }\r\n }\r\n\r\n /**\r\n * Activate the slide,\r\n * active slide is generally the current one,\r\n * meaning the user can see it.\r\n */\r\n activate() {\r\n if (this.instance.dispatch('contentActivate', { content: this }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (this.slide) {\r\n if (this.isImageContent() && this.isDecoding && !isSafari()) {\r\n // add image to slide when it becomes active,\r\n // even if it's not finished decoding\r\n this.appendImage();\r\n } else if (this.isError()) {\r\n this.load(false, true); // try to reload\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Deactivate the content\r\n */\r\n deactivate() {\r\n this.instance.dispatch('contentDeactivate', { content: this });\r\n }\r\n\r\n\r\n /**\r\n * Remove the content from DOM\r\n */\r\n remove() {\r\n this.isAttached = false;\r\n\r\n if (this.instance.dispatch('contentRemove', { content: this }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n if (this.element && this.element.parentNode) {\r\n this.element.remove();\r\n }\r\n\r\n if (this.placeholder && this.placeholder.element) {\r\n this.placeholder.element.remove();\r\n }\r\n }\r\n\r\n /**\r\n * Append the image content to slide container\r\n */\r\n appendImage() {\r\n if (!this.isAttached) {\r\n return;\r\n }\r\n\r\n if (this.instance.dispatch('contentAppendImage', { content: this }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n // ensure that element exists and is not already appended\r\n if (this.slide && this.element && !this.element.parentNode) {\r\n this.slide.container.appendChild(this.element);\r\n }\r\n\r\n if (this.state === LOAD_STATE.LOADED || this.state === LOAD_STATE.ERROR) {\r\n this.removePlaceholder();\r\n }\r\n }\r\n}\r\n\r\nexport default Content;\r\n","import { getViewportSize, getPanAreaSize } from '../util/viewport-size.js';\r\nimport ZoomLevel from './zoom-level.js';\r\n\r\n/** @typedef {import('./content.js').default} Content */\r\n/** @typedef {import('./slide.js').default} Slide */\r\n/** @typedef {import('./slide.js').SlideData} SlideData */\r\n/** @typedef {import('../core/base.js').default} PhotoSwipeBase */\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('../lightbox/lightbox.js').default} PhotoSwipeLightbox */\r\n\r\nconst MIN_SLIDES_TO_CACHE = 5;\r\n\r\n/**\r\n * Lazy-load an image\r\n * This function is used both by Lightbox and PhotoSwipe core,\r\n * thus it can be called before dialog is opened.\r\n *\r\n * @param {SlideData} itemData Data about the slide\r\n * @param {PhotoSwipe | PhotoSwipeLightbox | PhotoSwipeBase} instance PhotoSwipe instance\r\n * @param {number} index\r\n * @returns Image that is being decoded or false.\r\n */\r\nexport function lazyLoadData(itemData, instance, index) {\r\n // src/slide/content/content.js\r\n const content = instance.createContentFromData(itemData, index);\r\n\r\n if (!content || !content.lazyLoad) {\r\n return;\r\n }\r\n\r\n const { options } = instance;\r\n\r\n // We need to know dimensions of the image to preload it,\r\n // as it might use srcset and we need to define sizes\r\n // @ts-expect-error should provide pswp instance?\r\n const viewportSize = instance.viewportSize || getViewportSize(options, instance);\r\n const panAreaSize = getPanAreaSize(options, viewportSize, itemData, index);\r\n\r\n const zoomLevel = new ZoomLevel(options, itemData, -1);\r\n zoomLevel.update(content.width, content.height, panAreaSize);\r\n\r\n content.lazyLoad();\r\n content.setDisplayedSize(\r\n Math.ceil(content.width * zoomLevel.initial),\r\n Math.ceil(content.height * zoomLevel.initial)\r\n );\r\n\r\n return content;\r\n}\r\n\r\n\r\n/**\r\n * Lazy-loads specific slide.\r\n * This function is used both by Lightbox and PhotoSwipe core,\r\n * thus it can be called before dialog is opened.\r\n *\r\n * By default it loads image based on viewport size and initial zoom level.\r\n *\r\n * @param {number} index Slide index\r\n * @param {PhotoSwipe | PhotoSwipeLightbox} instance PhotoSwipe or PhotoSwipeLightbox eventable instance\r\n */\r\nexport function lazyLoadSlide(index, instance) {\r\n const itemData = instance.getItemData(index);\r\n\r\n if (instance.dispatch('lazyLoadSlide', { index, itemData }).defaultPrevented) {\r\n return;\r\n }\r\n\r\n return lazyLoadData(itemData, instance, index);\r\n}\r\n\r\n\r\nclass ContentLoader {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(pswp) {\r\n this.pswp = pswp;\r\n // Total amount of cached images\r\n this.limit = Math.max(\r\n pswp.options.preload[0] + pswp.options.preload[1] + 1,\r\n MIN_SLIDES_TO_CACHE\r\n );\r\n /** @type {Content[]} */\r\n this._cachedItems = [];\r\n }\r\n\r\n /**\r\n * Lazy load nearby slides based on `preload` option.\r\n *\r\n * @param {number=} diff Difference between slide indexes that was changed recently, or 0.\r\n */\r\n updateLazy(diff) {\r\n const { pswp } = this;\r\n\r\n if (pswp.dispatch('lazyLoad').defaultPrevented) {\r\n return;\r\n }\r\n\r\n const { preload } = pswp.options;\r\n const isForward = diff === undefined ? true : (diff >= 0);\r\n let i;\r\n\r\n // preload[1] - num items to preload in forward direction\r\n for (i = 0; i <= preload[1]; i++) {\r\n this.loadSlideByIndex(pswp.currIndex + (isForward ? i : (-i)));\r\n }\r\n\r\n // preload[0] - num items to preload in backward direction\r\n for (i = 1; i <= preload[0]; i++) {\r\n this.loadSlideByIndex(pswp.currIndex + (isForward ? (-i) : i));\r\n }\r\n }\r\n\r\n /**\r\n * @param {number} index\r\n */\r\n loadSlideByIndex(index) {\r\n index = this.pswp.getLoopedIndex(index);\r\n // try to get cached content\r\n let content = this.getContentByIndex(index);\r\n if (!content) {\r\n // no cached content, so try to load from scratch:\r\n content = lazyLoadSlide(index, this.pswp);\r\n // if content can be loaded, add it to cache:\r\n if (content) {\r\n this.addToCache(content);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @param {Slide} slide\r\n */\r\n getContentBySlide(slide) {\r\n let content = this.getContentByIndex(slide.index);\r\n if (!content) {\r\n // create content if not found in cache\r\n content = this.pswp.createContentFromData(slide.data, slide.index);\r\n if (content) {\r\n this.addToCache(content);\r\n }\r\n }\r\n\r\n if (content) {\r\n // assign slide to content\r\n content.setSlide(slide);\r\n }\r\n return content;\r\n }\r\n\r\n /**\r\n * @param {Content} content\r\n */\r\n addToCache(content) {\r\n // move to the end of array\r\n this.removeByIndex(content.index);\r\n this._cachedItems.push(content);\r\n\r\n if (this._cachedItems.length > this.limit) {\r\n // Destroy the first content that's not attached\r\n const indexToRemove = this._cachedItems.findIndex((item) => {\r\n return !item.isAttached && !item.hasSlide;\r\n });\r\n if (indexToRemove !== -1) {\r\n const removedItem = this._cachedItems.splice(indexToRemove, 1)[0];\r\n removedItem.destroy();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Removes an image from cache, does not destroy() it, just removes.\r\n *\r\n * @param {number} index\r\n */\r\n removeByIndex(index) {\r\n const indexToRemove = this._cachedItems.findIndex(item => item.index === index);\r\n if (indexToRemove !== -1) {\r\n this._cachedItems.splice(indexToRemove, 1);\r\n }\r\n }\r\n\r\n /**\r\n * @param {number} index\r\n */\r\n getContentByIndex(index) {\r\n return this._cachedItems.find(content => content.index === index);\r\n }\r\n\r\n destroy() {\r\n this._cachedItems.forEach(content => content.destroy());\r\n this._cachedItems = null;\r\n }\r\n}\r\n\r\nexport default ContentLoader;\r\n","import Eventable from './eventable.js';\r\nimport {\r\n getElementsFromOption\r\n} from '../util/util.js';\r\nimport Content from '../slide/content.js';\r\nimport { lazyLoadData } from '../slide/loader.js';\r\n\r\n/** @typedef {import(\"../photoswipe.js\").default} PhotoSwipe */\r\n/** @typedef {import(\"../photoswipe.js\").PhotoSwipeOptions} PhotoSwipeOptions */\r\n/** @typedef {import(\"../slide/slide.js\").SlideData} SlideData */\r\n\r\n/**\r\n * PhotoSwipe base class that can retrieve data about every slide.\r\n * Shared by PhotoSwipe Core and PhotoSwipe Lightbox\r\n */\r\nclass PhotoSwipeBase extends Eventable {\r\n /**\r\n * Get total number of slides\r\n *\r\n * @returns {number}\r\n */\r\n getNumItems() {\r\n let numItems;\r\n const { dataSource } = this.options;\r\n if (!dataSource) {\r\n numItems = 0;\r\n } else if ('length' in dataSource) {\r\n // may be an array or just object with length property\r\n numItems = dataSource.length;\r\n } else if ('gallery' in dataSource) {\r\n // query DOM elements\r\n if (!dataSource.items) {\r\n dataSource.items = this._getGalleryDOMElements(dataSource.gallery);\r\n }\r\n\r\n if (dataSource.items) {\r\n numItems = dataSource.items.length;\r\n }\r\n }\r\n\r\n // legacy event, before filters were introduced\r\n const event = this.dispatch('numItems', {\r\n dataSource,\r\n numItems\r\n });\r\n return this.applyFilters('numItems', event.numItems, dataSource);\r\n }\r\n\r\n /**\r\n * @param {SlideData} slideData\r\n * @param {number} index\r\n */\r\n createContentFromData(slideData, index) {\r\n // @ts-expect-error\r\n return new Content(slideData, this, index);\r\n }\r\n\r\n /**\r\n * Get item data by index.\r\n *\r\n * \"item data\" should contain normalized information that PhotoSwipe needs to generate a slide.\r\n * For example, it may contain properties like\r\n * `src`, `srcset`, `w`, `h`, which will be used to generate a slide with image.\r\n *\r\n * @param {number} index\r\n */\r\n getItemData(index) {\r\n const { dataSource } = this.options;\r\n let dataSourceItem;\r\n if (Array.isArray(dataSource)) {\r\n // Datasource is an array of elements\r\n dataSourceItem = dataSource[index];\r\n } else if (dataSource && dataSource.gallery) {\r\n // dataSource has gallery property,\r\n // thus it was created by Lightbox, based on\r\n // gallery and children options\r\n\r\n // query DOM elements\r\n if (!dataSource.items) {\r\n dataSource.items = this._getGalleryDOMElements(dataSource.gallery);\r\n }\r\n\r\n dataSourceItem = dataSource.items[index];\r\n }\r\n\r\n let itemData = dataSourceItem;\r\n\r\n if (itemData instanceof Element) {\r\n itemData = this._domElementToItemData(itemData);\r\n }\r\n\r\n // Dispatching the itemData event,\r\n // it's a legacy verion before filters were introduced\r\n const event = this.dispatch('itemData', {\r\n itemData: itemData || {},\r\n index\r\n });\r\n\r\n return this.applyFilters('itemData', event.itemData, index);\r\n }\r\n\r\n /**\r\n * Get array of gallery DOM elements,\r\n * based on childSelector and gallery element.\r\n *\r\n * @param {HTMLElement} galleryElement\r\n */\r\n _getGalleryDOMElements(galleryElement) {\r\n if (this.options.children || this.options.childSelector) {\r\n return getElementsFromOption(\r\n this.options.children,\r\n this.options.childSelector,\r\n galleryElement\r\n ) || [];\r\n }\r\n\r\n return [galleryElement];\r\n }\r\n\r\n /**\r\n * Converts DOM element to item data object.\r\n *\r\n * @param {HTMLElement} element DOM element\r\n */\r\n // eslint-disable-next-line class-methods-use-this\r\n _domElementToItemData(element) {\r\n /** @type {SlideData} */\r\n const itemData = {\r\n element\r\n };\r\n\r\n // eslint-disable-next-line max-len\r\n const linkEl = /** @type {HTMLAnchorElement} */ (element.tagName === 'A' ? element : element.querySelector('a'));\r\n\r\n if (linkEl) {\r\n // src comes from data-pswp-src attribute,\r\n // if it's empty link href is used\r\n itemData.src = linkEl.dataset.pswpSrc || linkEl.href;\r\n\r\n if (linkEl.dataset.pswpSrcset) {\r\n itemData.srcset = linkEl.dataset.pswpSrcset;\r\n }\r\n\r\n itemData.width = parseInt(linkEl.dataset.pswpWidth, 10);\r\n itemData.height = parseInt(linkEl.dataset.pswpHeight, 10);\r\n\r\n // support legacy w & h properties\r\n itemData.w = itemData.width;\r\n itemData.h = itemData.height;\r\n\r\n if (linkEl.dataset.pswpType) {\r\n itemData.type = linkEl.dataset.pswpType;\r\n }\r\n\r\n const thumbnailEl = element.querySelector('img');\r\n\r\n if (thumbnailEl) {\r\n // msrc is URL to placeholder image that's displayed before large image is loaded\r\n // by default it's displayed only for the first slide\r\n itemData.msrc = thumbnailEl.currentSrc || thumbnailEl.src;\r\n itemData.alt = thumbnailEl.getAttribute('alt');\r\n }\r\n\r\n if (linkEl.dataset.pswpCropped || linkEl.dataset.cropped) {\r\n itemData.thumbCropped = true;\r\n }\r\n }\r\n\r\n return this.applyFilters('domItemData', itemData, element, linkEl);\r\n }\r\n\r\n /**\r\n * Lazy-load by slide data\r\n *\r\n * @param {SlideData} itemData Data about the slide\r\n * @param {number} index\r\n * @returns Image that is being decoded or false.\r\n */\r\n lazyLoadData(itemData, index) {\r\n return lazyLoadData(itemData, this, index);\r\n }\r\n}\r\n\r\nexport default PhotoSwipeBase;\r\n","import {\r\n setTransform,\r\n equalizePoints,\r\n decodeImage,\r\n toTransformString\r\n} from './util/util.js';\r\n\r\n/** @typedef {import('./photoswipe.js').default} PhotoSwipe */\r\n/** @typedef {import('./slide/get-thumb-bounds.js').Bounds} Bounds */\r\n/** @typedef {import('./util/animations.js').AnimationProps} AnimationProps */\r\n\r\n// some browsers do not paint\r\n// elements which opacity is set to 0,\r\n// since we need to pre-render elements for the animation -\r\n// we set it to the minimum amount\r\nconst MIN_OPACITY = 0.003;\r\n\r\n/**\r\n * Manages opening and closing transitions of the PhotoSwipe.\r\n *\r\n * It can perform zoom, fade or no transition.\r\n */\r\nclass Opener {\r\n /**\r\n * @param {PhotoSwipe} pswp\r\n */\r\n constructor(pswp) {\r\n this.pswp = pswp;\r\n this.isClosed = true;\r\n this._prepareOpen = this._prepareOpen.bind(this);\r\n\r\n /** @type {false | Bounds} */\r\n this._thumbBounds = undefined;\r\n\r\n // Override initial zoom and pan position\r\n pswp.on('firstZoomPan', this._prepareOpen);\r\n }\r\n\r\n open() {\r\n this._prepareOpen();\r\n this._start();\r\n }\r\n\r\n close() {\r\n if (this.isClosed || this.isClosing || this.isOpening) {\r\n // if we close during opening animation\r\n // for now do nothing,\r\n // browsers aren't good at changing the direction of the CSS transition\r\n return false;\r\n }\r\n\r\n const slide = this.pswp.currSlide;\r\n\r\n this.isOpen = false;\r\n this.isOpening = false;\r\n this.isClosing = true;\r\n this._duration = this.pswp.options.hideAnimationDuration;\r\n\r\n if (slide && slide.currZoomLevel * slide.width >= this.pswp.options.maxWidthToAnimate) {\r\n this._duration = 0;\r\n }\r\n\r\n this._applyStartProps();\r\n setTimeout(() => {\r\n this._start();\r\n }, this._croppedZoom ? 30 : 0);\r\n\r\n return true;\r\n }\r\n\r\n _prepareOpen() {\r\n this.pswp.off('firstZoomPan', this._prepareOpen);\r\n if (!this.isOpening) {\r\n const slide = this.pswp.currSlide;\r\n this.isOpening = true;\r\n this.isClosing = false;\r\n this._duration = this.pswp.options.showAnimationDuration;\r\n if (slide && slide.zoomLevels.initial * slide.width >= this.pswp.options.maxWidthToAnimate) {\r\n this._duration = 0;\r\n }\r\n this._applyStartProps();\r\n }\r\n }\r\n\r\n _applyStartProps() {\r\n const { pswp } = this;\r\n const slide = this.pswp.currSlide;\r\n const { options } = pswp;\r\n\r\n if (options.showHideAnimationType === 'fade') {\r\n options.showHideOpacity = true;\r\n this._thumbBounds = false;\r\n } else if (options.showHideAnimationType === 'none') {\r\n options.showHideOpacity = false;\r\n this._duration = 0;\r\n this._thumbBounds = false;\r\n } else if (this.isOpening && pswp._initialThumbBounds) {\r\n // Use initial bounds if defined\r\n this._thumbBounds = pswp._initialThumbBounds;\r\n } else {\r\n this._thumbBounds = this.pswp.getThumbBounds();\r\n }\r\n\r\n this._placeholder = slide.getPlaceholderElement();\r\n\r\n pswp.animations.stopAll();\r\n\r\n // Discard animations when duration is less than 50ms\r\n this._useAnimation = (this._duration > 50);\r\n this._animateZoom = Boolean(this._thumbBounds)\r\n && (slide.content && slide.content.usePlaceholder())\r\n && (!this.isClosing || !pswp.mainScroll.isShifted());\r\n if (!this._animateZoom) {\r\n this._animateRootOpacity = true;\r\n\r\n if (this.isOpening) {\r\n slide.zoomAndPanToInitial();\r\n slide.applyCurrentZoomPan();\r\n }\r\n } else {\r\n this._animateRootOpacity = options.showHideOpacity;\r\n }\r\n this._animateBgOpacity = !this._animateRootOpacity && this.pswp.options.bgOpacity > MIN_OPACITY;\r\n this._opacityElement = this._animateRootOpacity ? pswp.element : pswp.bg;\r\n\r\n if (!this._useAnimation) {\r\n this._duration = 0;\r\n this._animateZoom = false;\r\n this._animateBgOpacity = false;\r\n this._animateRootOpacity = true;\r\n if (this.isOpening) {\r\n pswp.element.style.opacity = String(MIN_OPACITY);\r\n pswp.applyBgOpacity(1);\r\n }\r\n return;\r\n }\r\n\r\n if (this._animateZoom && this._thumbBounds && this._thumbBounds.innerRect) {\r\n // Properties are used when animation from cropped thumbnail\r\n this._croppedZoom = true;\r\n this._cropContainer1 = this.pswp.container;\r\n this._cropContainer2 = this.pswp.currSlide.holderElement;\r\n\r\n pswp.container.style.overflow = 'hidden';\r\n pswp.container.style.width = pswp.viewportSize.x + 'px';\r\n } else {\r\n this._croppedZoom = false;\r\n }\r\n\r\n if (this.isOpening) {\r\n // Apply styles before opening transition\r\n if (this._animateRootOpacity) {\r\n pswp.element.style.opacity = String(MIN_OPACITY);\r\n pswp.applyBgOpacity(1);\r\n } else {\r\n if (this._animateBgOpacity) {\r\n pswp.bg.style.opacity = String(MIN_OPACITY);\r\n }\r\n pswp.element.style.opacity = '1';\r\n }\r\n\r\n if (this._animateZoom) {\r\n this._setClosedStateZoomPan();\r\n if (this._placeholder) {\r\n // tell browser that we plan to animate the placeholder\r\n this._placeholder.style.willChange = 'transform';\r\n\r\n // hide placeholder to allow hiding of\r\n // elements that overlap it (such as icons over the thumbnail)\r\n this._placeholder.style.opacity = String(MIN_OPACITY);\r\n }\r\n }\r\n } else if (this.isClosing) {\r\n // hide nearby slides to make sure that\r\n // they are not painted during the transition\r\n pswp.mainScroll.itemHolders[0].el.style.display = 'none';\r\n pswp.mainScroll.itemHolders[2].el.style.display = 'none';\r\n\r\n if (this._croppedZoom) {\r\n if (pswp.mainScroll.x !== 0) {\r\n // shift the main scroller to zero position\r\n pswp.mainScroll.resetPosition();\r\n pswp.mainScroll.resize();\r\n }\r\n }\r\n }\r\n }\r\n\r\n _start() {\r\n if (this.isOpening\r\n && this._useAnimation\r\n && this._placeholder\r\n && this._placeholder.tagName === 'IMG') {\r\n // To ensure smooth animation\r\n // we wait till the current slide image placeholder is decoded,\r\n // but no longer than 250ms,\r\n // and no shorter than 50ms\r\n // (just using requestanimationframe is not enough in Firefox,\r\n // for some reason)\r\n new Promise((resolve) => {\r\n let decoded = false;\r\n let isDelaying = true;\r\n decodeImage(/** @type {HTMLImageElement} */ (this._placeholder)).finally(() => {\r\n decoded = true;\r\n if (!isDelaying) {\r\n resolve();\r\n }\r\n });\r\n setTimeout(() => {\r\n isDelaying = false;\r\n if (decoded) {\r\n resolve();\r\n }\r\n }, 50);\r\n setTimeout(resolve, 250);\r\n }).finally(() => this._initiate());\r\n } else {\r\n this._initiate();\r\n }\r\n }\r\n\r\n _initiate() {\r\n this.pswp.element.style.setProperty('--pswp-transition-duration', this._duration + 'ms');\r\n\r\n this.pswp.dispatch(\r\n this.isOpening ? 'openingAnimationStart' : 'closingAnimationStart'\r\n );\r\n\r\n // legacy event\r\n this.pswp.dispatch(\r\n /** @type {'initialZoomIn' | 'initialZoomOut'} */\r\n ('initialZoom' + (this.isOpening ? 'In' : 'Out'))\r\n );\r\n\r\n this.pswp.element.classList[this.isOpening ? 'add' : 'remove']('pswp--ui-visible');\r\n\r\n if (this.isOpening) {\r\n if (this._placeholder) {\r\n // unhide the placeholder\r\n this._placeholder.style.opacity = '1';\r\n }\r\n this._animateToOpenState();\r\n } else if (this.isClosing) {\r\n this._animateToClosedState();\r\n }\r\n\r\n if (!this._useAnimation) {\r\n this._onAnimationComplete();\r\n }\r\n }\r\n\r\n _onAnimationComplete() {\r\n const { pswp } = this;\r\n this.isOpen = this.isOpening;\r\n this.isClosed = this.isClosing;\r\n this.isOpening = false;\r\n this.isClosing = false;\r\n\r\n pswp.dispatch(\r\n this.isOpen ? 'openingAnimationEnd' : 'closingAnimationEnd'\r\n );\r\n\r\n // legacy event\r\n pswp.dispatch(\r\n /** @type {'initialZoomInEnd' | 'initialZoomOutEnd'} */\r\n ('initialZoom' + (this.isOpen ? 'InEnd' : 'OutEnd'))\r\n );\r\n\r\n if (this.isClosed) {\r\n pswp.destroy();\r\n } else if (this.isOpen) {\r\n if (this._animateZoom) {\r\n pswp.container.style.overflow = 'visible';\r\n pswp.container.style.width = '100%';\r\n }\r\n pswp.currSlide.applyCurrentZoomPan();\r\n }\r\n }\r\n\r\n _animateToOpenState() {\r\n const { pswp } = this;\r\n if (this._animateZoom) {\r\n if (this._croppedZoom) {\r\n this._animateTo(this._cropContainer1, 'transform', 'translate3d(0,0,0)');\r\n this._animateTo(this._cropContainer2, 'transform', 'none');\r\n }\r\n\r\n pswp.currSlide.zoomAndPanToInitial();\r\n this._animateTo(\r\n pswp.currSlide.container,\r\n 'transform',\r\n pswp.currSlide.getCurrentTransform()\r\n );\r\n }\r\n\r\n if (this._animateBgOpacity) {\r\n this._animateTo(pswp.bg, 'opacity', String(pswp.options.bgOpacity));\r\n }\r\n\r\n if (this._animateRootOpacity) {\r\n this._animateTo(pswp.element, 'opacity', '1');\r\n }\r\n }\r\n\r\n _animateToClosedState() {\r\n const { pswp } = this;\r\n\r\n if (this._animateZoom) {\r\n this._setClosedStateZoomPan(true);\r\n }\r\n\r\n if (this._animateBgOpacity\r\n && pswp.bgOpacity > 0.01) { // do not animate opacity if it's already at 0\r\n this._animateTo(pswp.bg, 'opacity', '0');\r\n }\r\n\r\n if (this._animateRootOpacity) {\r\n this._animateTo(pswp.element, 'opacity', '0');\r\n }\r\n }\r\n\r\n /**\r\n * @param {boolean=} animate\r\n */\r\n _setClosedStateZoomPan(animate) {\r\n if (!this._thumbBounds) return;\r\n\r\n const { pswp } = this;\r\n const { innerRect } = this._thumbBounds;\r\n const { currSlide, viewportSize } = pswp;\r\n\r\n if (this._croppedZoom) {\r\n const containerOnePanX = -viewportSize.x + (this._thumbBounds.x - innerRect.x) + innerRect.w;\r\n const containerOnePanY = -viewportSize.y + (this._thumbBounds.y - innerRect.y) + innerRect.h;\r\n const containerTwoPanX = viewportSize.x - innerRect.w;\r\n const containerTwoPanY = viewportSize.y - innerRect.h;\r\n\r\n\r\n if (animate) {\r\n this._animateTo(\r\n this._cropContainer1,\r\n 'transform',\r\n toTransformString(containerOnePanX, containerOnePanY)\r\n );\r\n\r\n this._animateTo(\r\n this._cropContainer2,\r\n 'transform',\r\n toTransformString(containerTwoPanX, containerTwoPanY)\r\n );\r\n } else {\r\n setTransform(this._cropContainer1, containerOnePanX, containerOnePanY);\r\n setTransform(this._cropContainer2, containerTwoPanX, containerTwoPanY);\r\n }\r\n }\r\n\r\n equalizePoints(currSlide.pan, innerRect || this._thumbBounds);\r\n currSlide.currZoomLevel = this._thumbBounds.w / currSlide.width;\r\n\r\n if (animate) {\r\n this._animateTo(currSlide.container, 'transform', currSlide.getCurrentTransform());\r\n } else {\r\n currSlide.applyCurrentZoomPan();\r\n }\r\n }\r\n\r\n /**\r\n * @param {HTMLElement} target\r\n * @param {'transform' | 'opacity'} prop\r\n * @param {string} propValue\r\n */\r\n _animateTo(target, prop, propValue) {\r\n if (!this._duration) {\r\n target.style[prop] = propValue;\r\n return;\r\n }\r\n\r\n const { animations } = this.pswp;\r\n /** @type {AnimationProps} */\r\n const animProps = {\r\n duration: this._duration,\r\n easing: this.pswp.options.easing,\r\n onComplete: () => {\r\n if (!animations.activeAnimations.length) {\r\n this._onAnimationComplete();\r\n }\r\n },\r\n target,\r\n };\r\n animProps[prop] = propValue;\r\n animations.startTransition(animProps);\r\n }\r\n}\r\n\r\nexport default Opener;\r\n","import {\r\n createElement,\r\n equalizePoints,\r\n pointsEqual,\r\n clamp,\r\n} from './util/util.js';\r\n\r\nimport DOMEvents from './util/dom-events.js';\r\nimport Slide from './slide/slide.js';\r\nimport Gestures from './gestures/gestures.js';\r\nimport MainScroll from './main-scroll.js';\r\n\r\nimport Keyboard from './keyboard.js';\r\nimport Animations from './util/animations.js';\r\nimport ScrollWheel from './scroll-wheel.js';\r\nimport UI from './ui/ui.js';\r\nimport { getViewportSize } from './util/viewport-size.js';\r\nimport { getThumbBounds } from './slide/get-thumb-bounds.js';\r\nimport PhotoSwipeBase from './core/base.js';\r\nimport Opener from './opener.js';\r\nimport ContentLoader from './slide/loader.js';\r\n\r\n/**\r\n * @template T\r\n * @typedef {import('./types.js').Type} Type\r\n */\r\n\r\n/** @typedef {import('./slide/slide.js').SlideData} SlideData */\r\n/** @typedef {import('./slide/zoom-level.js').ZoomLevelOption} ZoomLevelOption */\r\n/** @typedef {import('./ui/ui-element.js').UIElementData} UIElementData */\r\n/** @typedef {import('./main-scroll.js').ItemHolder} ItemHolder */\r\n/** @typedef {import('./core/eventable.js').PhotoSwipeEventsMap} PhotoSwipeEventsMap */\r\n/** @typedef {import('./core/eventable.js').PhotoSwipeFiltersMap} PhotoSwipeFiltersMap */\r\n/**\r\n * @template T\r\n * @typedef {import('./core/eventable.js').EventCallback} EventCallback\r\n */\r\n/**\r\n * @template T\r\n * @typedef {import('./core/eventable.js').AugmentedEvent} AugmentedEvent\r\n */\r\n\r\n/** @typedef {{ x?: number; y?: number; id?: string | number }} Point */\r\n/** @typedef {{ x?: number; y?: number }} Size */\r\n/** @typedef {{ top: number; bottom: number; left: number; right: number }} Padding */\r\n/** @typedef {SlideData[]} DataSourceArray */\r\n/** @typedef {{ gallery: HTMLElement; items?: HTMLElement[] }} DataSourceObject */\r\n/** @typedef {DataSourceArray | DataSourceObject} DataSource */\r\n/** @typedef {(point: Point, originalEvent: PointerEvent) => void} ActionFn */\r\n/** @typedef {'close' | 'next' | 'zoom' | 'zoom-or-close' | 'toggle-controls'} ActionType */\r\n/** @typedef {Type | { default: Type }} PhotoSwipeModule */\r\n/** @typedef {PhotoSwipeModule | Promise | (() => Promise)} PhotoSwipeModuleOption */\r\n\r\n/**\r\n * @typedef {Object} PhotoSwipeOptions https://photoswipe.com/options/\r\n *\r\n * @prop {DataSource=} dataSource\r\n * Pass an array of any items via dataSource option. Its length will determine amount of slides\r\n * (which may be modified further from numItems event).\r\n *\r\n * Each item should contain data that you need to generate slide\r\n * (for image slide it would be src (image URL), width (image width), height, srcset, alt).\r\n *\r\n * If these properties are not present in your initial array, you may \"pre-parse\" each item from itemData filter.\r\n *\r\n * @prop {number=} bgOpacity\r\n * Background backdrop opacity, always define it via this option and not via CSS rgba color.\r\n *\r\n * @prop {number=} spacing\r\n * Spacing between slides. Defined as ratio relative to the viewport width (0.1 = 10% of viewport).\r\n *\r\n * @prop {boolean=} allowPanToNext\r\n * Allow swipe navigation to the next slide when the current slide is zoomed. Does not apply to mouse events.\r\n *\r\n * @prop {boolean=} loop\r\n * If set to true you'll be able to swipe from the last to the first image.\r\n * Option is always false when there are less than 3 slides.\r\n *\r\n * @prop {boolean=} wheelToZoom\r\n * By default PhotoSwipe zooms image with ctrl-wheel, if you enable this option - image will zoom just via wheel.\r\n *\r\n * @prop {boolean=} pinchToClose\r\n * Pinch touch gesture to close the gallery.\r\n *\r\n * @prop {boolean=} closeOnVerticalDrag\r\n * Vertical drag gesture to close the PhotoSwipe.\r\n *\r\n * @prop {Padding=} padding\r\n * Slide area padding (in pixels).\r\n *\r\n * @prop {(viewportSize: Size, itemData: SlideData, index: number) => Padding} [paddingFn]\r\n * The option is checked frequently, so make sure it's performant. Overrides padding option if defined. For example:\r\n *\r\n * @prop {number | false} [hideAnimationDuration]\r\n * Transition duration in milliseconds, can be 0.\r\n *\r\n * @prop {number | false} [showAnimationDuration]\r\n * Transition duration in milliseconds, can be 0.\r\n *\r\n * @prop {number | false} [zoomAnimationDuration]\r\n * Transition duration in milliseconds, can be 0.\r\n *\r\n * @prop {string=} easing\r\n * String, 'cubic-bezier(.4,0,.22,1)'. CSS easing function for open/close/zoom transitions.\r\n *\r\n * @prop {boolean=} escKey\r\n * Esc key to close.\r\n *\r\n * @prop {boolean=} arrowKeys\r\n * Left/right arrow keys for navigation.\r\n *\r\n * @prop {boolean=} returnFocus\r\n * Restore focus the last active element after PhotoSwipe is closed.\r\n *\r\n * @prop {boolean=} clickToCloseNonZoomable\r\n * If image is not zoomable (for example, smaller than viewport) it can be closed by clicking on it.\r\n *\r\n * @prop {ActionType | ActionFn | false} [imageClickAction]\r\n * Refer to click and tap actions page.\r\n *\r\n * @prop {ActionType | ActionFn | false} [bgClickAction]\r\n * Refer to click and tap actions page.\r\n *\r\n * @prop {ActionType | ActionFn | false} [tapAction]\r\n * Refer to click and tap actions page.\r\n *\r\n * @prop {ActionType | ActionFn | false} [doubleTapAction]\r\n * Refer to click and tap actions page.\r\n *\r\n * @prop {number=} preloaderDelay\r\n * Delay before the loading indicator will be displayed,\r\n * if image is loaded during it - the indicator will not be displayed at all. Can be zero.\r\n *\r\n * @prop {string=} indexIndicatorSep\r\n * Used for slide count indicator (\"1 of 10 \").\r\n *\r\n * @prop {(options: PhotoSwipeOptions, pswp: PhotoSwipe) => { x: number; y: number }} [getViewportSizeFn]\r\n * A function that should return slide viewport width and height, in format {x: 100, y: 100}.\r\n *\r\n * @prop {string=} errorMsg\r\n * Message to display when the image wasn't able to load. If you need to display HTML - use contentErrorElement filter.\r\n *\r\n * @prop {[number, number]=} preload\r\n * Lazy loading of nearby slides based on direction of movement. Should be an array with two integers,\r\n * first one - number of items to preload before the current image, second one - after the current image.\r\n * Two nearby images are always loaded.\r\n *\r\n * @prop {string=} mainClass\r\n * Class that will be added to the root element of PhotoSwipe, may contain multiple separated by space.\r\n * Example on Styling page.\r\n *\r\n * @prop {HTMLElement=} appendToEl\r\n * Element to which PhotoSwipe dialog will be appended when it opens.\r\n *\r\n * @prop {number=} maxWidthToAnimate\r\n * Maximum width of image to animate, if initial rendered image width\r\n * is larger than this value - the opening/closing transition will be automatically disabled.\r\n *\r\n * @prop {string=} closeTitle\r\n * Translating\r\n *\r\n * @prop {string=} zoomTitle\r\n * Translating\r\n *\r\n * @prop {string=} arrowPrevTitle\r\n * Translating\r\n *\r\n * @prop {string=} arrowNextTitle\r\n * Translating\r\n *\r\n * @prop {'zoom' | 'fade' | 'none'} [showHideAnimationType]\r\n * To adjust opening or closing transition type use lightbox option `showHideAnimationType` (`String`).\r\n * It supports three values - `zoom` (default), `fade` (default if there is no thumbnail) and `none`.\r\n *\r\n * Animations are automatically disabled if user `(prefers-reduced-motion: reduce)`.\r\n *\r\n * @prop {number=} index\r\n * Defines start slide index.\r\n *\r\n * @prop {(e: MouseEvent) => number} [getClickedIndexFn]\r\n *\r\n * @prop {boolean=} arrowPrev\r\n * @prop {boolean=} arrowNext\r\n * @prop {boolean=} zoom\r\n * @prop {boolean=} close\r\n * @prop {boolean=} counter\r\n *\r\n * @prop {string=} arrowPrevSVG\r\n * @prop {string=} arrowNextSVG\r\n * @prop {string=} zoomSVG\r\n * @prop {string=} closeSVG\r\n * @prop {string=} counterSVG\r\n *\r\n * @prop {string=} arrowPrevTitle\r\n * @prop {string=} arrowNextTitle\r\n * @prop {string=} zoomTitle\r\n * @prop {string=} closeTitle\r\n * @prop {string=} counterTitle\r\n *\r\n * @prop {ZoomLevelOption=} initialZoomLevel\r\n * @prop {ZoomLevelOption=} secondaryZoomLevel\r\n * @prop {ZoomLevelOption=} maxZoomLevel\r\n *\r\n * @prop {boolean=} mouseMovePan\r\n * @prop {Point | null} [initialPointerPos]\r\n * @prop {boolean=} showHideOpacity\r\n *\r\n * @prop {PhotoSwipeModuleOption} [pswpModule]\r\n * @prop {() => Promise} [openPromise]\r\n * @prop {boolean=} preloadFirstSlide\r\n * @prop {string=} gallery\r\n * @prop {string=} gallerySelector\r\n * @prop {string=} children\r\n * @prop {string=} childSelector\r\n * @prop {string | false} [thumbSelector]\r\n */\r\n\r\n/** @type {PhotoSwipeOptions} */\r\nconst defaultOptions = {\r\n allowPanToNext: true,\r\n spacing: 0.1,\r\n loop: true,\r\n pinchToClose: true,\r\n closeOnVerticalDrag: true,\r\n hideAnimationDuration: 333,\r\n showAnimationDuration: 333,\r\n zoomAnimationDuration: 333,\r\n escKey: true,\r\n arrowKeys: true,\r\n returnFocus: true,\r\n maxWidthToAnimate: 4000,\r\n clickToCloseNonZoomable: true,\r\n imageClickAction: 'zoom-or-close',\r\n bgClickAction: 'close',\r\n tapAction: 'toggle-controls',\r\n doubleTapAction: 'zoom',\r\n indexIndicatorSep: ' / ',\r\n preloaderDelay: 2000,\r\n bgOpacity: 0.8,\r\n\r\n index: 0,\r\n errorMsg: 'The image cannot be loaded',\r\n preload: [1, 2],\r\n easing: 'cubic-bezier(.4,0,.22,1)'\r\n};\r\n\r\n/**\r\n * PhotoSwipe Core\r\n */\r\nclass PhotoSwipe extends PhotoSwipeBase {\r\n /**\r\n * @param {PhotoSwipeOptions} options\r\n */\r\n constructor(options) {\r\n super();\r\n\r\n this._prepareOptions(options);\r\n\r\n /**\r\n * offset of viewport relative to document\r\n *\r\n * @type {{ x?: number; y?: number }}\r\n */\r\n this.offset = {};\r\n\r\n /**\r\n * @type {{ x?: number; y?: number }}\r\n * @private\r\n */\r\n this._prevViewportSize = {};\r\n\r\n /**\r\n * Size of scrollable PhotoSwipe viewport\r\n *\r\n * @type {{ x?: number; y?: number }}\r\n */\r\n this.viewportSize = {};\r\n\r\n /**\r\n * background (backdrop) opacity\r\n *\r\n * @type {number}\r\n */\r\n this.bgOpacity = 1;\r\n\r\n /** @type {HTMLDivElement} */\r\n this.topBar = undefined;\r\n\r\n this.events = new DOMEvents();\r\n\r\n /** @type {Animations} */\r\n this.animations = new Animations();\r\n\r\n this.mainScroll = new MainScroll(this);\r\n this.gestures = new Gestures(this);\r\n this.opener = new Opener(this);\r\n this.keyboard = new Keyboard(this);\r\n this.contentLoader = new ContentLoader(this);\r\n }\r\n\r\n init() {\r\n if (this.isOpen || this.isDestroying) {\r\n return;\r\n }\r\n\r\n this.isOpen = true;\r\n this.dispatch('init'); // legacy\r\n this.dispatch('beforeOpen');\r\n\r\n this._createMainStructure();\r\n\r\n // add classes to the root element of PhotoSwipe\r\n let rootClasses = 'pswp--open';\r\n if (this.gestures.supportsTouch) {\r\n rootClasses += ' pswp--touch';\r\n }\r\n if (this.options.mainClass) {\r\n rootClasses += ' ' + this.options.mainClass;\r\n }\r\n this.element.className += ' ' + rootClasses;\r\n\r\n this.currIndex = this.options.index || 0;\r\n this.potentialIndex = this.currIndex;\r\n this.dispatch('firstUpdate'); // starting index can be modified here\r\n\r\n // initialize scroll wheel handler to block the scroll\r\n this.scrollWheel = new ScrollWheel(this);\r\n\r\n // sanitize index\r\n if (Number.isNaN(this.currIndex)\r\n || this.currIndex < 0\r\n || this.currIndex >= this.getNumItems()) {\r\n this.currIndex = 0;\r\n }\r\n\r\n if (!this.gestures.supportsTouch) {\r\n // enable mouse features if no touch support detected\r\n this.mouseDetected();\r\n }\r\n\r\n // causes forced synchronous layout\r\n this.updateSize();\r\n\r\n this.offset.y = window.pageYOffset;\r\n\r\n this._initialItemData = this.getItemData(this.currIndex);\r\n this.dispatch('gettingData', {\r\n index: this.currIndex,\r\n data: this._initialItemData,\r\n slide: undefined\r\n });\r\n\r\n // *Layout* - calculate size and position of elements here\r\n this._initialThumbBounds = this.getThumbBounds();\r\n this.dispatch('initialLayout');\r\n\r\n this.on('openingAnimationEnd', () => {\r\n this.mainScroll.itemHolders[0].el.style.display = 'block';\r\n this.mainScroll.itemHolders[2].el.style.display = 'block';\r\n\r\n // Add content to the previous and next slide\r\n this.setContent(this.mainScroll.itemHolders[0], this.currIndex - 1);\r\n this.setContent(this.mainScroll.itemHolders[2], this.currIndex + 1);\r\n\r\n this.appendHeavy();\r\n\r\n this.contentLoader.updateLazy();\r\n\r\n this.events.add(window, 'resize', this._handlePageResize.bind(this));\r\n this.events.add(window, 'scroll', this._updatePageScrollOffset.bind(this));\r\n this.dispatch('bindEvents');\r\n });\r\n\r\n // set content for center slide (first time)\r\n this.setContent(this.mainScroll.itemHolders[1], this.currIndex);\r\n this.dispatch('change');\r\n\r\n this.opener.open();\r\n\r\n this.dispatch('afterInit');\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get looped slide index\r\n * (for example, -1 will return the last slide)\r\n *\r\n * @param {number} index\r\n */\r\n getLoopedIndex(index) {\r\n const numSlides = this.getNumItems();\r\n\r\n if (this.options.loop) {\r\n if (index > numSlides - 1) {\r\n index -= numSlides;\r\n }\r\n\r\n if (index < 0) {\r\n index += numSlides;\r\n }\r\n }\r\n\r\n index = clamp(index, 0, numSlides - 1);\r\n\r\n return index;\r\n }\r\n\r\n appendHeavy() {\r\n this.mainScroll.itemHolders.forEach((itemHolder) => {\r\n if (itemHolder.slide) {\r\n itemHolder.slide.appendHeavy();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Change the slide\r\n * @param {number} index New index\r\n */\r\n goTo(index) {\r\n this.mainScroll.moveIndexBy(\r\n this.getLoopedIndex(index) - this.potentialIndex\r\n );\r\n }\r\n\r\n /**\r\n * Go to the next slide.\r\n */\r\n next() {\r\n this.goTo(this.potentialIndex + 1);\r\n }\r\n\r\n /**\r\n * Go to the previous slide.\r\n */\r\n prev() {\r\n this.goTo(this.potentialIndex - 1);\r\n }\r\n\r\n /**\r\n * @see slide/slide.js zoomTo\r\n *\r\n * @param {Parameters} args\r\n */\r\n zoomTo(...args) {\r\n this.currSlide.zoomTo(...args);\r\n }\r\n\r\n /**\r\n * @see slide/slide.js toggleZoom\r\n */\r\n toggleZoom() {\r\n this.currSlide.toggleZoom();\r\n }\r\n\r\n /**\r\n * Close the gallery.\r\n * After closing transition ends - destroy it\r\n */\r\n close() {\r\n if (!this.opener.isOpen || this.isDestroying) {\r\n return;\r\n }\r\n\r\n this.isDestroying = true;\r\n\r\n this.dispatch('close');\r\n\r\n this.events.removeAll();\r\n this.opener.close();\r\n }\r\n\r\n /**\r\n * Destroys the gallery:\r\n * - instantly closes the gallery\r\n * - unbinds events,\r\n * - cleans intervals and timeouts\r\n * - removes elements from DOM\r\n */\r\n destroy() {\r\n if (!this.isDestroying) {\r\n this.options.showHideAnimationType = 'none';\r\n this.close();\r\n return;\r\n }\r\n\r\n this.dispatch('destroy');\r\n\r\n this.listeners = null;\r\n\r\n this.scrollWrap.ontouchmove = null;\r\n this.scrollWrap.ontouchend = null;\r\n\r\n this.element.remove();\r\n\r\n this.mainScroll.itemHolders.forEach((itemHolder) => {\r\n if (itemHolder.slide) {\r\n itemHolder.slide.destroy();\r\n }\r\n });\r\n\r\n this.contentLoader.destroy();\r\n this.events.removeAll();\r\n }\r\n\r\n /**\r\n * Refresh/reload content of a slide by its index\r\n *\r\n * @param {number} slideIndex\r\n */\r\n refreshSlideContent(slideIndex) {\r\n this.contentLoader.removeByIndex(slideIndex);\r\n this.mainScroll.itemHolders.forEach((itemHolder, i) => {\r\n let potentialHolderIndex = this.currSlide.index - 1 + i;\r\n if (this.canLoop()) {\r\n potentialHolderIndex = this.getLoopedIndex(potentialHolderIndex);\r\n }\r\n if (potentialHolderIndex === slideIndex) {\r\n // set the new slide content\r\n this.setContent(itemHolder, slideIndex, true);\r\n\r\n // activate the new slide if it's current\r\n if (i === 1) {\r\n /** @type {Slide} */\r\n this.currSlide = itemHolder.slide;\r\n itemHolder.slide.setIsActive(true);\r\n }\r\n }\r\n });\r\n\r\n this.dispatch('change');\r\n }\r\n\r\n\r\n /**\r\n * Set slide content\r\n *\r\n * @param {ItemHolder} holder mainScroll.itemHolders array item\r\n * @param {number} index Slide index\r\n * @param {boolean=} force If content should be set even if index wasn't changed\r\n */\r\n setContent(holder, index, force) {\r\n if (this.canLoop()) {\r\n index = this.getLoopedIndex(index);\r\n }\r\n\r\n if (holder.slide) {\r\n if (holder.slide.index === index && !force) {\r\n // exit if holder already contains this slide\r\n // this could be common when just three slides are used\r\n return;\r\n }\r\n\r\n // destroy previous slide\r\n holder.slide.destroy();\r\n holder.slide = null;\r\n }\r\n\r\n // exit if no loop and index is out of bounds\r\n if (!this.canLoop() && (index < 0 || index >= this.getNumItems())) {\r\n return;\r\n }\r\n\r\n const itemData = this.getItemData(index);\r\n holder.slide = new Slide(itemData, index, this);\r\n\r\n // set current slide\r\n if (index === this.currIndex) {\r\n this.currSlide = holder.slide;\r\n }\r\n\r\n holder.slide.append(holder.el);\r\n }\r\n\r\n getViewportCenterPoint() {\r\n return {\r\n x: this.viewportSize.x / 2,\r\n y: this.viewportSize.y / 2\r\n };\r\n }\r\n\r\n /**\r\n * Update size of all elements.\r\n * Executed on init and on page resize.\r\n *\r\n * @param {boolean=} force Update size even if size of viewport was not changed.\r\n */\r\n updateSize(force) {\r\n // let item;\r\n // let itemIndex;\r\n\r\n if (this.isDestroying) {\r\n // exit if PhotoSwipe is closed or closing\r\n // (to avoid errors, as resize event might be delayed)\r\n return;\r\n }\r\n\r\n //const newWidth = this.scrollWrap.clientWidth;\r\n //const newHeight = this.scrollWrap.clientHeight;\r\n\r\n const newViewportSize = getViewportSize(this.options, this);\r\n\r\n if (!force && pointsEqual(newViewportSize, this._prevViewportSize)) {\r\n // Exit if dimensions were not changed\r\n return;\r\n }\r\n\r\n //this._prevViewportSize.x = newWidth;\r\n //this._prevViewportSize.y = newHeight;\r\n equalizePoints(this._prevViewportSize, newViewportSize);\r\n\r\n this.dispatch('beforeResize');\r\n\r\n equalizePoints(this.viewportSize, this._prevViewportSize);\r\n\r\n this._updatePageScrollOffset();\r\n\r\n this.dispatch('viewportSize');\r\n\r\n // Resize slides only after opener animation is finished\r\n // and don't re-calculate size on inital size update\r\n this.mainScroll.resize(this.opener.isOpen);\r\n\r\n if (!this.hasMouse && window.matchMedia('(any-hover: hover)').matches) {\r\n this.mouseDetected();\r\n }\r\n\r\n this.dispatch('resize');\r\n }\r\n\r\n /**\r\n * @param {number} opacity\r\n */\r\n applyBgOpacity(opacity) {\r\n this.bgOpacity = Math.max(opacity, 0);\r\n this.bg.style.opacity = String(this.bgOpacity * this.options.bgOpacity);\r\n }\r\n\r\n /**\r\n * Whether mouse is detected\r\n */\r\n mouseDetected() {\r\n if (!this.hasMouse) {\r\n this.hasMouse = true;\r\n this.element.classList.add('pswp--has_mouse');\r\n }\r\n }\r\n\r\n /**\r\n * Page resize event handler\r\n *\r\n * @private\r\n */\r\n _handlePageResize() {\r\n this.updateSize();\r\n\r\n // In iOS webview, if element size depends on document size,\r\n // it'll be measured incorrectly in resize event\r\n //\r\n // https://bugs.webkit.org/show_bug.cgi?id=170595\r\n // https://hackernoon.com/onresize-event-broken-in-mobile-safari-d8469027bf4d\r\n if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) {\r\n setTimeout(() => {\r\n this.updateSize();\r\n }, 500);\r\n }\r\n }\r\n\r\n /**\r\n * Page scroll offset is used\r\n * to get correct coordinates\r\n * relative to PhotoSwipe viewport.\r\n *\r\n * @private\r\n */\r\n _updatePageScrollOffset() {\r\n this.setScrollOffset(0, window.pageYOffset);\r\n }\r\n\r\n /**\r\n * @param {number} x\r\n * @param {number} y\r\n */\r\n setScrollOffset(x, y) {\r\n this.offset.x = x;\r\n this.offset.y = y;\r\n this.dispatch('updateScrollOffset');\r\n }\r\n\r\n /**\r\n * Create main HTML structure of PhotoSwipe,\r\n * and add it to DOM\r\n *\r\n * @private\r\n */\r\n _createMainStructure() {\r\n // root DOM element of PhotoSwipe (.pswp)\r\n this.element = createElement('pswp');\r\n this.element.setAttribute('tabindex', '-1');\r\n this.element.setAttribute('role', 'dialog');\r\n\r\n // template is legacy prop\r\n this.template = this.element;\r\n\r\n // Background is added as a separate element,\r\n // as animating opacity is faster than animating rgba()\r\n this.bg = createElement('pswp__bg', false, this.element);\r\n this.scrollWrap = createElement('pswp__scroll-wrap', false, this.element);\r\n this.container = createElement('pswp__container', false, this.scrollWrap);\r\n\r\n this.mainScroll.appendHolders();\r\n\r\n this.ui = new UI(this);\r\n this.ui.init();\r\n\r\n // append to DOM\r\n (this.options.appendToEl || document.body).appendChild(this.element);\r\n }\r\n\r\n\r\n /**\r\n * Get position and dimensions of small thumbnail\r\n * {x:,y:,w:}\r\n *\r\n * Height is optional (calculated based on the large image)\r\n */\r\n getThumbBounds() {\r\n return getThumbBounds(\r\n this.currIndex,\r\n this.currSlide ? this.currSlide.data : this._initialItemData,\r\n this\r\n );\r\n }\r\n\r\n /**\r\n * If the PhotoSwipe can have continious loop\r\n * @returns Boolean\r\n */\r\n canLoop() {\r\n return (this.options.loop && this.getNumItems() > 2);\r\n }\r\n\r\n /**\r\n * @param {PhotoSwipeOptions} options\r\n * @private\r\n */\r\n _prepareOptions(options) {\r\n if (window.matchMedia('(prefers-reduced-motion), (update: slow)').matches) {\r\n options.showHideAnimationType = 'none';\r\n options.zoomAnimationDuration = 0;\r\n }\r\n\r\n /** @type {PhotoSwipeOptions}*/\r\n this.options = {\r\n ...defaultOptions,\r\n ...options\r\n };\r\n }\r\n}\r\n\r\nexport default PhotoSwipe;\r\n","/** @typedef {import('./slide.js').SlideData} SlideData */\r\n/** @typedef {import('../photoswipe.js').default} PhotoSwipe */\r\n\r\n/** @typedef {{ x: number; y: number; w: number; innerRect?: { w: number; h: number; x: number; y: number } }} Bounds */\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n */\r\nfunction getBoundsByElement(el) {\r\n const thumbAreaRect = el.getBoundingClientRect();\r\n return {\r\n x: thumbAreaRect.left,\r\n y: thumbAreaRect.top,\r\n w: thumbAreaRect.width\r\n };\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {number} imageWidth\r\n * @param {number} imageHeight\r\n */\r\nfunction getCroppedBoundsByElement(el, imageWidth, imageHeight) {\r\n const thumbAreaRect = el.getBoundingClientRect();\r\n\r\n // fill image into the area\r\n // (do they same as object-fit:cover does to retrieve coordinates)\r\n const hRatio = thumbAreaRect.width / imageWidth;\r\n const vRatio = thumbAreaRect.height / imageHeight;\r\n const fillZoomLevel = hRatio > vRatio ? hRatio : vRatio;\r\n\r\n const offsetX = (thumbAreaRect.width - imageWidth * fillZoomLevel) / 2;\r\n const offsetY = (thumbAreaRect.height - imageHeight * fillZoomLevel) / 2;\r\n\r\n /**\r\n * Coordinates of the image,\r\n * as if it was not cropped,\r\n * height is calculated automatically\r\n *\r\n * @type {Bounds}\r\n */\r\n const bounds = {\r\n x: thumbAreaRect.left + offsetX,\r\n y: thumbAreaRect.top + offsetY,\r\n w: imageWidth * fillZoomLevel\r\n };\r\n\r\n // Coordinates of inner crop area\r\n // relative to the image\r\n bounds.innerRect = {\r\n w: thumbAreaRect.width,\r\n h: thumbAreaRect.height,\r\n x: offsetX,\r\n y: offsetY\r\n };\r\n\r\n return bounds;\r\n}\r\n\r\n/**\r\n * Get dimensions of thumbnail image\r\n * (click on which opens photoswipe or closes photoswipe to)\r\n *\r\n * @param {number} index\r\n * @param {SlideData} itemData\r\n * @param {PhotoSwipe} instance PhotoSwipe instance\r\n * @returns {Bounds | undefined}\r\n */\r\nexport function getThumbBounds(index, itemData, instance) {\r\n // legacy event, before filters were introduced\r\n const event = instance.dispatch('thumbBounds', {\r\n index,\r\n itemData,\r\n instance\r\n });\r\n // @ts-expect-error\r\n if (event.thumbBounds) {\r\n // @ts-expect-error\r\n return event.thumbBounds;\r\n }\r\n\r\n const { element } = itemData;\r\n let thumbBounds;\r\n /** @type {HTMLElement} */\r\n let thumbnail;\r\n\r\n if (element && instance.options.thumbSelector !== false) {\r\n const thumbSelector = instance.options.thumbSelector || 'img';\r\n thumbnail = element.matches(thumbSelector)\r\n ? element : element.querySelector(thumbSelector);\r\n }\r\n\r\n thumbnail = instance.applyFilters('thumbEl', thumbnail, itemData, index);\r\n\r\n if (thumbnail) {\r\n if (!itemData.thumbCropped) {\r\n thumbBounds = getBoundsByElement(thumbnail);\r\n } else {\r\n thumbBounds = getCroppedBoundsByElement(\r\n thumbnail,\r\n itemData.width || itemData.w,\r\n itemData.height || itemData.h\r\n );\r\n }\r\n }\r\n\r\n return instance.applyFilters('thumbBounds', thumbBounds, itemData, index);\r\n}\r\n"],"names":["createElement","className","tagName","appendToEl","el","document","appendChild","equalizePoints","p1","p2","x","y","undefined","id","roundPoint","p","Math","round","getDistanceBetween","abs","sqrt","pointsEqual","clamp","val","min","max","toTransformString","scale","propValue","setTransform","style","transform","setTransitionStyle","prop","duration","ease","transition","setWidthHeight","w","h","width","height","LOAD_STATE","isSafari","navigator","vendor","match","supportsPassive","window","addEventListener","Object","defineProperty","get","e","DOMEvents","this","_pool","target","type","listener","passive","_toggleListener","forEach","poolItem","unbind","skipPool","methodName","split","eType","filter","push","eventOptions","getViewportSize","options","pswp","getViewportSizeFn","newViewportSize","documentElement","clientWidth","innerHeight","parsePaddingOption","viewportSize","itemData","index","paddingValue","paddingFn","padding","legacyPropName","toUpperCase","slice","getPanAreaSize","PanBounds","slide","currZoomLevel","center","reset","_updateAxis","dispatch","axis","elSize","data","panAreaSize","panOffset","ZoomLevel","maxWidth","maxHeight","elementSize","hRatio","vRatio","fit","fill","vFill","initial","_getInitial","secondary","_getSecondary","_getMax","zoomLevels","slideData","optionPrefix","optionName","optionValue","Number","_parseZoomLevelOption","Slide","isActive","currIndex","currentResolution","isFirstSlide","opener","isOpen","pan","content","contentLoader","getContentBySlide","container","bounds","prevDisplayedWidth","prevDisplayedHeight","activate","deactivate","holderElement","transformOrigin","calculateSize","load","updateContentSize","appendHeavy","zoomAndPanToInitial","applyCurrentZoomPan","heavyAppended","mainScroll","isShifted","defaultPrevented","append","hasSlide","remove","update","panTo","force","scaleMultiplier","sizeChanged","setDisplayedSize","placeholder","element","destZoomLevel","centerPoint","transitionDuration","ignoreBounds","isZoomable","animations","stopAllPan","prevZoomLevel","setZoomLevel","calculateZoomToPanOffset","finishTransition","_setResolution","startTransition","isPan","name","getCurrentTransform","onComplete","easing","zoomTo","zoomAnimationDuration","point","getViewportCenterPoint","zoomFactor","correctPan","panX","panY","_applyZoomTransform","currSlide","zoom","newResolution","DragHandler","gestures","startPan","stopAll","prevP1","dragAxis","closeOnVerticalDrag","isMultitouch","_setPanWithFriction","bgOpacity","_getVerticalDragRatio","applyBgOpacity","_panOrMoveMainScroll","velocity","indexDiff","currentSlideVisibilityRatio","getCurrSlideX","moveIndexBy","correctZoomPan","_finishPanGestureForAxis","panPos","restoreBgOpacity","projectedPosition","initialVelocity","decelerationRate","project","vDragRatio","projectedVDragRatio","close","correctedPanPosition","dampingRatio","initialBgOpacity","totalPanDist","startSpring","start","end","onUpdate","pos","animationProgressRatio","floor","delta","newMainScrollX","isPannable","moveTo","newPan","allowPanToNext","currSlideMainScrollX","mainScrollShiftDiff","isLeftToRight","isRightToLeft","potentialPan","customFriction","getZoomPointsCenter","ZoomHandler","_startPan","_startZoomPoint","_zoomPoint","_startZoomLevel","_wasOverFitZoomLevel","startP1","startP2","minZoomLevel","maxZoomLevel","pinchToClose","_calculatePanForZoomLevel","ignoreGesture","destinationZoomLevel","currZoomLevelNeedsChange","initialPan","destinationPan","panNeedsChange","naturalFrequency","now","newZoomLevel","didTapOnMainContent","event","closest","TapHandler","originalEvent","targetClassList","classList","isImageClick","contains","isBackgroundClick","_doClickOrTapAction","actionName","actionFullName","toggleZoom","clickToCloseNonZoomable","toggle","call","Gestures","prevP2","_lastStartP1","_intervalP1","_numActivePoints","_ongoingPointers","_touchEventEnabled","_pointerEventEnabled","PointerEvent","supportsTouch","maxTouchPoints","drag","tapHandler","on","events","add","scrollWrap","_onClick","_bindEvents","ontouchmove","ontouchend","pref","down","up","cancel","cancelEvent","onPointerDown","bind","onPointerMove","onPointerUp","isMousePointer","pointerType","button","mouseDetected","_preventPointerEventBehaviour","_updatePoints","pointerDown","_clearTapTimer","preventDefault","isDragging","isZooming","_finishDrag","_updateStartPoints","_rafStopLoop","_rafRenderLoop","_calculateDragDirection","_intervalTime","Date","_velocityCalculated","_updateVelocity","_finishTap","change","_updatePrevPoints","raf","requestAnimationFrame","time","_getVelocity","indexOf","tapDelay","doubleTapAction","_tapTimer","doubleTap","setTimeout","tap","click","clearTimeout","displacement","cancelAnimationFrame","pointerEvent","pointerIndex","findIndex","ongoingPoiner","pointerId","splice","_convertEventPosToPoint","length","touchEvent","touches","diff","axisToCheck","pageX","offset","pageY","identifier","stopPropagation","MainScroll","slideWidth","itemHolders","resetPosition","resizeSlides","newSlideWidth","spacing","slideWidthChanged","itemHolder","_containerShiftIndex","resize","_currPositionIndex","_prevPositionIndex","i","display","getNumItems","animate","velocityX","newIndex","potentialIndex","numSlides","canLoop","getLoopedIndex","distance","stopMainScroll","destinationX","isMainScroll","updateCurrItem","currDiff","currDistance","positionDifference","tempHolder","diffAbs","shift","setContent","pop","unshift","setIsActive","updateLazy","dragging","newSlideIndexOffset","Keyboard","initialPointerPos","_focusRoot","_onFocusIn","_onKeyDown","lastActiveElement","activeElement","returnFocus","_wasFocused","focus","which","ctrlKey","metaKey","altKey","shiftKey","specialKeyUsed","keydownAction","isForward","keyCode","escKey","arrowKeys","template","CSSAnimation","props","onFinish","_target","_onComplete","_onTransitionEnd","_helperTimeout","_finalizeAnimation","_finished","removeEventListener","SpringEaser","_dampingRatio","_naturalFrequency","_dampedFrequency","deltaPosition","deltaTime","coeff","naturalDumpingPow","E","dumpedFCos","cos","dumpedFSin","sin","SpringAnimation","easer","prevTime","_raf","animationLoop","easeFrame","Animations","activeAnimations","_start","isSpring","animation","stop","destroy","some","ScrollWheel","_onWheel","deltaX","deltaY","wheelToZoom","deltaMode","clientX","clientY","UIElement","elementHTML","html","isButton","toLowerCase","title","ariaLabel","setAttribute","innerHTML","htmlData","isCustomSVG","svgData","out","join","size","outlineID","inner","addElementHTML","onInit","onClick","onclick","appendTo","topBar","applyFilters","initArrowButton","isNextButton","loop","disabled","arrowPrev","order","arrowNext","closeButton","zoomButton","loadingIndicator","indicatorElement","isVisible","delayTimeout","setIndicatorVisibility","visible","updatePreloaderVisibility","isLoading","preloaderDelay","ui","counterIndicator","counterElement","innerText","indexIndicatorSep","setZoomedIn","isZoomedIn","UI","_lastUpdatedZoomLevel","isRegistered","uiElementsData","sort","a","b","items","uiElementData","registerElement","_onZoomPanUpdate","elementData","isClosing","currZoomLevelDiff","imageClickAction","PhotoSwipeEvent","details","assign","Eventable","_listeners","_filters","fn","priority","f1","f2","addFilter","removeFilter","args","apply","off","Placeholder","imageSrc","decoding","alt","src","parentNode","Content","instance","displayedImageWidth","displayedImageHeight","isAttached","state","keepPlaceholder","isLazy","reload","usePlaceholder","placeholderEl","parentElement","prepend","placeholderSrc","msrc","isImageContent","loadImage","imageElement","updateSrcsetSizes","srcset","complete","onLoaded","onload","onerror","onError","removePlaceholder","displayError","isError","isInitialSizeUpdate","image","sizesWidth","dataset","largestUsedSize","parseInt","sizes","String","errorMsgEl","errorMsg","supportsDecode","isDecoding","decode","finally","appendImage","lazyLoadData","createContentFromData","lazyLoad","zoomLevel","ceil","ContentLoader","limit","preload","_cachedItems","loadSlideByIndex","getContentByIndex","getItemData","lazyLoadSlide","addToCache","setSlide","removeByIndex","indexToRemove","item","find","PhotoSwipeBase","numItems","dataSource","_getGalleryDOMElements","gallery","dataSourceItem","Array","isArray","Element","_domElementToItemData","galleryElement","children","childSelector","option","legacySelector","parent","elements","NodeList","from","selector","querySelectorAll","getElementsFromOption","linkEl","querySelector","pswpSrc","href","pswpSrcset","pswpWidth","pswpHeight","pswpType","thumbnailEl","currentSrc","getAttribute","pswpCropped","cropped","thumbCropped","MIN_OPACITY","Opener","isClosed","_prepareOpen","_thumbBounds","isOpening","_duration","hideAnimationDuration","maxWidthToAnimate","_applyStartProps","_croppedZoom","showAnimationDuration","showHideAnimationType","showHideOpacity","_initialThumbBounds","getThumbBounds","_placeholder","getPlaceholderElement","_useAnimation","_animateZoom","Boolean","_animateRootOpacity","_animateBgOpacity","_opacityElement","bg","opacity","innerRect","_cropContainer1","_cropContainer2","overflow","_setClosedStateZoomPan","willChange","Promise","resolve","img","decoded","isDelaying","reject","_initiate","setProperty","_animateToOpenState","_animateToClosedState","_onAnimationComplete","_animateTo","containerOnePanX","containerOnePanY","containerTwoPanX","containerTwoPanY","animProps","defaultOptions","bgClickAction","tapAction","PhotoSwipe","_prepareOptions","_prevViewportSize","keyboard","isDestroying","_createMainStructure","rootClasses","mainClass","scrollWheel","isNaN","updateSize","pageYOffset","_initialItemData","_handlePageResize","_updatePageScrollOffset","open","goTo","removeAll","listeners","slideIndex","potentialHolderIndex","holder","hasMouse","matchMedia","matches","test","userAgent","setScrollOffset","appendHolders","init","body","thumbBounds","thumbnail","thumbAreaRect","thumbSelector","imageWidth","imageHeight","getBoundingClientRect","fillZoomLevel","offsetX","offsetY","left","top","getCroppedBoundsByElement"],"sourceRoot":""}