UNPKG

flickrgallery

Version:
2,957 lines 99.6 kB
/*!
  * PhotoSwipe 5.4.4 - https://photoswipe.com
  * (c) 2024 Dmytro Semenov
  */
function f(r, t, i) {
  const e = document.createElement(t);
  return r && (e.className = r), i && i.appendChild(e), e;
}
function p(r, t) {
  return r.x = t.x, r.y = t.y, t.id !== void 0 && (r.id = t.id), r;
}
function Z(r) {
  r.x = Math.round(r.x), r.y = Math.round(r.y);
}
function A(r, t) {
  const i = Math.abs(r.x - t.x), e = Math.abs(r.y - t.y);
  return Math.sqrt(i * i + e * e);
}
function x(r, t) {
  return r.x === t.x && r.y === t.y;
}
function b(r, t, i) {
  return Math.min(Math.max(r, t), i);
}
function I(r, t, i) {
  let e = `translate3d(${r}px,${t || 0}px,0)`;
  return i !== void 0 && (e += ` scale3d(${i},${i},1)`), e;
}
function y(r, t, i, e) {
  r.style.transform = I(t, i, e);
}
const W = "cubic-bezier(.4,0,.22,1)";
function D(r, t, i, e) {
  r.style.transition = t ? `${t} ${i}ms ${e || W}` : "none";
}
function L(r, t, i) {
  r.style.width = typeof t == "number" ? `${t}px` : t, r.style.height = typeof i == "number" ? `${i}px` : i;
}
function V(r) {
  D(r);
}
function $(r) {
  return "decode" in r ? r.decode().catch(() => {
  }) : r.complete ? Promise.resolve(r) : new Promise((t, i) => {
    r.onload = () => t(r), r.onerror = i;
  });
}
const _ = {
  IDLE: "idle",
  LOADING: "loading",
  LOADED: "loaded",
  ERROR: "error"
};
function U(r) {
  return "button" in r && r.button === 1 || r.ctrlKey || r.metaKey || r.altKey || r.shiftKey;
}
function q(r, t, i = document) {
  let e = [];
  if (r instanceof Element)
    e = [r];
  else if (r instanceof NodeList || Array.isArray(r))
    e = Array.from(r);
  else {
    const s = typeof r == "string" ? r : t;
    s && (e = Array.from(i.querySelectorAll(s)));
  }
  return e;
}
function C() {
  return !!(navigator.vendor && navigator.vendor.match(/apple/i));
}
let M = !1;
try {
  window.addEventListener("test", null, Object.defineProperty({}, "passive", {
    get: () => {
      M = !0;
    }
  }));
} catch {
}
class G {
  constructor() {
    this._pool = [];
  }
  /**
   * Adds event listeners
   *
   * @param {PoolItem['target']} target
   * @param {PoolItem['type']} type Can be multiple, separated by space.
   * @param {PoolItem['listener']} listener
   * @param {PoolItem['passive']} [passive]
   */
  add(t, i, e, s) {
    this._toggleListener(t, i, e, s);
  }
  /**
   * Removes event listeners
   *
   * @param {PoolItem['target']} target
   * @param {PoolItem['type']} type
   * @param {PoolItem['listener']} listener
   * @param {PoolItem['passive']} [passive]
   */
  remove(t, i, e, s) {
    this._toggleListener(t, i, e, s, !0);
  }
  /**
   * Removes all bound events
   */
  removeAll() {
    this._pool.forEach((t) => {
      this._toggleListener(t.target, t.type, t.listener, t.passive, !0, !0);
    }), this._pool = [];
  }
  /**
   * Adds or removes event
   *
   * @private
   * @param {PoolItem['target']} target
   * @param {PoolItem['type']} type
   * @param {PoolItem['listener']} listener
   * @param {PoolItem['passive']} [passive]
   * @param {boolean} [unbind] Whether the event should be added or removed
   * @param {boolean} [skipPool] Whether events pool should be skipped
   */
  _toggleListener(t, i, e, s, n, o) {
    if (!t)
      return;
    const a = n ? "removeEventListener" : "addEventListener";
    i.split(" ").forEach((l) => {
      if (l) {
        o || (n ? this._pool = this._pool.filter((d) => d.type !== l || d.listener !== e || d.target !== t) : this._pool.push({
          target: t,
          type: l,
          listener: e,
          passive: s
        }));
        const c = M ? {
          passive: s || !1
        } : !1;
        t[a](l, e, c);
      }
    });
  }
}
function R(r, t) {
  if (r.getViewportSizeFn) {
    const i = r.getViewportSizeFn(r, t);
    if (i)
      return i;
  }
  return {
    x: document.documentElement.clientWidth,
    // TODO: height on mobile is very incosistent due to toolbar
    // find a way to improve this
    //
    // document.documentElement.clientHeight - doesn't seem to work well
    y: window.innerHeight
  };
}
function S(r, t, i, e, s) {
  let n = 0;
  if (t.paddingFn)
    n = t.paddingFn(i, e, s)[r];
  else if (t.padding)
    n = t.padding[r];
  else {
    const o = "padding" + r[0].toUpperCase() + r.slice(1);
    t[o] && (n = t[o]);
  }
  return Number(n) || 0;
}
function F(r, t, i, e) {
  return {
    x: t.x - S("left", r, t, i, e) - S("right", r, t, i, e),
    y: t.y - S("top", r, t, i, e) - S("bottom", r, t, i, e)
  };
}
class K {
  /**
   * @param {Slide} slide
   */
  constructor(t) {
    this.slide = t, this.currZoomLevel = 1, this.center = /** @type {Point} */
    {
      x: 0,
      y: 0
    }, this.max = /** @type {Point} */
    {
      x: 0,
      y: 0
    }, this.min = /** @type {Point} */
    {
      x: 0,
      y: 0
    };
  }
  /**
   * _getItemBounds
   *
   * @param {number} currZoomLevel
   */
  update(t) {
    this.currZoomLevel = t, this.slide.width ? (this._updateAxis("x"), this._updateAxis("y"), this.slide.pswp.dispatch("calcBounds", {
      slide: this.slide
    })) : this.reset();
  }
  /**
   * _calculateItemBoundsForAxis
   *
   * @param {Axis} axis
   */
  _updateAxis(t) {
    const {
      pswp: i
    } = this.slide, e = this.slide[t === "x" ? "width" : "height"] * this.currZoomLevel, n = S(t === "x" ? "left" : "top", i.options, i.viewportSize, this.slide.data, this.slide.index), o = this.slide.panAreaSize[t];
    this.center[t] = Math.round((o - e) / 2) + n, this.max[t] = e > o ? Math.round(o - e) + n : this.center[t], this.min[t] = e > o ? n : this.center[t];
  }
  // _getZeroBounds
  reset() {
    this.center.x = 0, this.center.y = 0, this.max.x = 0, this.max.y = 0, this.min.x = 0, this.min.y = 0;
  }
  /**
   * Correct pan position if it's beyond the bounds
   *
   * @param {Axis} axis x or y
   * @param {number} panOffset
   * @returns {number}
   */
  correctPan(t, i) {
    return b(i, this.max[t], this.min[t]);
  }
}
const T = 4e3;
class B {
  /**
   * @param {PhotoSwipeOptions} options PhotoSwipe options
   * @param {SlideData} itemData Slide data
   * @param {number} index Slide index
   * @param {PhotoSwipe} [pswp] PhotoSwipe instance, can be undefined if not initialized yet
   */
  constructor(t, i, e, s) {
    this.pswp = s, this.options = t, this.itemData = i, this.index = e, this.panAreaSize = null, this.elementSize = null, this.fit = 1, this.fill = 1, this.vFill = 1, this.initial = 1, this.secondary = 1, this.max = 1, this.min = 1;
  }
  /**
   * Calculate initial, secondary and maximum zoom level for the specified slide.
   *
   * It should be called when either image or viewport size changes.
   *
   * @param {number} maxWidth
   * @param {number} maxHeight
   * @param {Point} panAreaSize
   */
  update(t, i, e) {
    const s = {
      x: t,
      y: i
    };
    this.elementSize = s, this.panAreaSize = e;
    const n = e.x / s.x, o = e.y / s.y;
    this.fit = Math.min(1, n < o ? n : o), this.fill = Math.min(1, n > o ? n : o), this.vFill = Math.min(1, o), this.initial = this._getInitial(), this.secondary = this._getSecondary(), this.max = Math.max(this.initial, this.secondary, this._getMax()), this.min = Math.min(this.fit, this.initial, this.secondary), this.pswp && this.pswp.dispatch("zoomLevelsUpdate", {
      zoomLevels: this,
      slideData: this.itemData
    });
  }
  /**
   * Parses user-defined zoom option.
   *
   * @private
   * @param {'initial' | 'secondary' | 'max'} optionPrefix Zoom level option prefix (initial, secondary, max)
   * @returns { number | undefined }
   */
  _parseZoomLevelOption(t) {
    const i = (
      /** @type {'initialZoomLevel' | 'secondaryZoomLevel' | 'maxZoomLevel'} */
      t + "ZoomLevel"
    ), e = this.options[i];
    if (e)
      return typeof e == "function" ? e(this) : e === "fill" ? this.fill : e === "fit" ? this.fit : Number(e);
  }
  /**
   * Get zoom level to which image will be zoomed after double-tap gesture,
   * or when user clicks on zoom icon,
   * or mouse-click on image itself.
   * If you return 1 image will be zoomed to its original size.
   *
   * @private
   * @return {number}
   */
  _getSecondary() {
    let t = this._parseZoomLevelOption("secondary");
    return t || (t = Math.min(1, this.fit * 3), this.elementSize && t * this.elementSize.x > T && (t = T / this.elementSize.x), t);
  }
  /**
   * Get initial image zoom level.
   *
   * @private
   * @return {number}
   */
  _getInitial() {
    return this._parseZoomLevelOption("initial") || this.fit;
  }
  /**
   * Maximum zoom level when user zooms
   * via zoom/pinch gesture,
   * via cmd/ctrl-wheel or via trackpad.
   *
   * @private
   * @return {number}
   */
  _getMax() {
    return this._parseZoomLevelOption("max") || Math.max(1, this.fit * 4);
  }
}
class X {
  /**
   * @param {SlideData} data
   * @param {number} index
   * @param {PhotoSwipe} pswp
   */
  constructor(t, i, e) {
    this.data = t, this.index = i, this.pswp = e, this.isActive = i === e.currIndex, this.currentResolution = 0, this.panAreaSize = {
      x: 0,
      y: 0
    }, this.pan = {
      x: 0,
      y: 0
    }, this.isFirstSlide = this.isActive && !e.opener.isOpen, this.zoomLevels = new B(e.options, t, i, e), this.pswp.dispatch("gettingData", {
      slide: this,
      data: this.data,
      index: i
    }), this.content = this.pswp.contentLoader.getContentBySlide(this), this.container = f("pswp__zoom-wrap", "div"), this.holderElement = null, this.currZoomLevel = 1, this.width = this.content.width, this.height = this.content.height, this.heavyAppended = !1, this.bounds = new K(this), this.prevDisplayedWidth = -1, this.prevDisplayedHeight = -1, this.pswp.dispatch("slideInit", {
      slide: this
    });
  }
  /**
   * If this slide is active/current/visible
   *
   * @param {boolean} isActive
   */
  setIsActive(t) {
    t && !this.isActive ? this.activate() : !t && this.isActive && this.deactivate();
  }
  /**
   * Appends slide content to DOM
   *
   * @param {HTMLElement} holderElement
   */
  append(t) {
    this.holderElement = t, this.container.style.transformOrigin = "0 0", this.data && (this.calculateSize(), this.load(), this.updateContentSize(), this.appendHeavy(), this.holderElement.appendChild(this.container), this.zoomAndPanToInitial(), this.pswp.dispatch("firstZoomPan", {
      slide: this
    }), this.applyCurrentZoomPan(), this.pswp.dispatch("afterSetContent", {
      slide: this
    }), this.isActive && this.activate());
  }
  load() {
    this.content.load(!1), this.pswp.dispatch("slideLoad", {
      slide: this
    });
  }
  /**
   * Append "heavy" DOM elements
   *
   * This may depend on a type of slide,
   * but generally these are large images.
   */
  appendHeavy() {
    const {
      pswp: t
    } = this;
    this.heavyAppended || !t.opener.isOpen || t.mainScroll.isShifted() || !this.isActive && !1 || this.pswp.dispatch("appendHeavy", {
      slide: this
    }).defaultPrevented || (this.heavyAppended = !0, this.content.append(), this.pswp.dispatch("appendHeavyContent", {
      slide: this
    }));
  }
  /**
   * Triggered when this slide is active (selected).
   *
   * If it's part of opening/closing transition -
   * activate() will trigger after the transition is ended.
   */
  activate() {
    this.isActive = !0, this.appendHeavy(), this.content.activate(), this.pswp.dispatch("slideActivate", {
      slide: this
    });
  }
  /**
   * Triggered when this slide becomes inactive.
   *
   * Slide can become inactive only after it was active.
   */
  deactivate() {
    this.isActive = !1, this.content.deactivate(), this.currZoomLevel !== this.zoomLevels.initial && this.calculateSize(), this.currentResolution = 0, this.zoomAndPanToInitial(), this.applyCurrentZoomPan(), this.updateContentSize(), this.pswp.dispatch("slideDeactivate", {
      slide: this
    });
  }
  /**
   * The slide should destroy itself, it will never be used again.
   * (unbind all events and destroy internal components)
   */
  destroy() {
    this.content.hasSlide = !1, this.content.remove(), this.container.remove(), this.pswp.dispatch("slideDestroy", {
      slide: this
    });
  }
  resize() {
    this.currZoomLevel === this.zoomLevels.initial || !this.isActive ? (this.calculateSize(), this.currentResolution = 0, this.zoomAndPanToInitial(), this.applyCurrentZoomPan(), this.updateContentSize()) : (this.calculateSize(), this.bounds.update(this.currZoomLevel), this.panTo(this.pan.x, this.pan.y));
  }
  /**
   * Apply size to current slide content,
   * based on the current resolution and scale.
   *
   * @param {boolean} [force] if size should be updated even if dimensions weren't changed
   */
  updateContentSize(t) {
    const i = this.currentResolution || this.zoomLevels.initial;
    if (!i)
      return;
    const e = Math.round(this.width * i) || this.pswp.viewportSize.x, s = Math.round(this.height * i) || this.pswp.viewportSize.y;
    !this.sizeChanged(e, s) && !t || this.content.setDisplayedSize(e, s);
  }
  /**
   * @param {number} width
   * @param {number} height
   */
  sizeChanged(t, i) {
    return t !== this.prevDisplayedWidth || i !== this.prevDisplayedHeight ? (this.prevDisplayedWidth = t, this.prevDisplayedHeight = i, !0) : !1;
  }
  /** @returns {HTMLImageElement | HTMLDivElement | null | undefined} */
  getPlaceholderElement() {
    var t;
    return (t = this.content.placeholder) === null || t === void 0 ? void 0 : t.element;
  }
  /**
   * Zoom current slide image to...
   *
   * @param {number} destZoomLevel Destination zoom level.
   * @param {Point} [centerPoint]
   * Transform origin center point, or false if viewport center should be used.
   * @param {number | false} [transitionDuration] Transition duration, may be set to 0.
   * @param {boolean} [ignoreBounds] Minimum and maximum zoom levels will be ignored.
   */
  zoomTo(t, i, e, s) {
    const {
      pswp: n
    } = this;
    if (!this.isZoomable() || n.mainScroll.isShifted())
      return;
    n.dispatch("beforeZoomTo", {
      destZoomLevel: t,
      centerPoint: i,
      transitionDuration: e
    }), n.animations.stopAllPan();
    const o = this.currZoomLevel;
    s || (t = b(t, this.zoomLevels.min, this.zoomLevels.max)), this.setZoomLevel(t), this.pan.x = this.calculateZoomToPanOffset("x", i, o), this.pan.y = this.calculateZoomToPanOffset("y", i, o), Z(this.pan);
    const a = () => {
      this._setResolution(t), this.applyCurrentZoomPan();
    };
    e ? n.animations.startTransition({
      isPan: !0,
      name: "zoomTo",
      target: this.container,
      transform: this.getCurrentTransform(),
      onComplete: a,
      duration: e,
      easing: n.options.easing
    }) : a();
  }
  /**
   * @param {Point} [centerPoint]
   */
  toggleZoom(t) {
    this.zoomTo(this.currZoomLevel === this.zoomLevels.initial ? this.zoomLevels.secondary : this.zoomLevels.initial, t, this.pswp.options.zoomAnimationDuration);
  }
  /**
   * Updates zoom level property and recalculates new pan bounds,
   * unlike zoomTo it does not apply transform (use applyCurrentZoomPan)
   *
   * @param {number} currZoomLevel
   */
  setZoomLevel(t) {
    this.currZoomLevel = t, this.bounds.update(this.currZoomLevel);
  }
  /**
   * Get pan position after zoom at a given `point`.
   *
   * Always call setZoomLevel(newZoomLevel) beforehand to recalculate
   * pan bounds according to the new zoom level.
   *
   * @param {'x' | 'y'} axis
   * @param {Point} [point]
   * point based on which zoom is performed, usually refers to the current mouse position,
   * if false - viewport center will be used.
   * @param {number} [prevZoomLevel] Zoom level before new zoom was applied.
   * @returns {number}
   */
  calculateZoomToPanOffset(t, i, e) {
    if (this.bounds.max[t] - this.bounds.min[t] === 0)
      return this.bounds.center[t];
    i || (i = this.pswp.getViewportCenterPoint()), e || (e = this.zoomLevels.initial);
    const n = this.currZoomLevel / e;
    return this.bounds.correctPan(t, (this.pan[t] - i[t]) * n + i[t]);
  }
  /**
   * Apply pan and keep it within bounds.
   *
   * @param {number} panX
   * @param {number} panY
   */
  panTo(t, i) {
    this.pan.x = this.bounds.correctPan("x", t), this.pan.y = this.bounds.correctPan("y", i), this.applyCurrentZoomPan();
  }
  /**
   * If the slide in the current state can be panned by the user
   * @returns {boolean}
   */
  isPannable() {
    return !!this.width && this.currZoomLevel > this.zoomLevels.fit;
  }
  /**
   * If the slide can be zoomed
   * @returns {boolean}
   */
  isZoomable() {
    return !!this.width && this.content.isZoomable();
  }
  /**
   * Apply transform and scale based on
   * the current pan position (this.pan) and zoom level (this.currZoomLevel)
   */
  applyCurrentZoomPan() {
    this._applyZoomTransform(this.pan.x, this.pan.y, this.currZoomLevel), this === this.pswp.currSlide && this.pswp.dispatch("zoomPanUpdate", {
      slide: this
    });
  }
  zoomAndPanToInitial() {
    this.currZoomLevel = this.zoomLevels.initial, this.bounds.update(this.currZoomLevel), p(this.pan, this.bounds.center), this.pswp.dispatch("initialZoomPan", {
      slide: this
    });
  }
  /**
   * Set translate and scale based on current resolution
   *
   * @param {number} x
   * @param {number} y
   * @param {number} zoom
   * @private
   */
  _applyZoomTransform(t, i, e) {
    e /= this.currentResolution || this.zoomLevels.initial, y(this.container, t, i, e);
  }
  calculateSize() {
    const {
      pswp: t
    } = this;
    p(this.panAreaSize, F(t.options, t.viewportSize, this.data, this.index)), this.zoomLevels.update(this.width, this.height, this.panAreaSize), t.dispatch("calcSlideSize", {
      slide: this
    });
  }
  /** @returns {string} */
  getCurrentTransform() {
    const t = this.currZoomLevel / (this.currentResolution || this.zoomLevels.initial);
    return I(this.pan.x, this.pan.y, t);
  }
  /**
   * Set resolution and re-render the image.
   *
   * For example, if the real image size is 2000x1500,
   * and resolution is 0.5 - it will be rendered as 1000x750.
   *
   * Image with zoom level 2 and resolution 0.5 is
   * the same as image with zoom level 1 and resolution 1.
   *
   * Used to optimize animations and make
   * sure that browser renders image in the highest quality.
   * Also used by responsive images to load the correct one.
   *
   * @param {number} newResolution
   */
  _setResolution(t) {
    t !== this.currentResolution && (this.currentResolution = t, this.updateContentSize(), this.pswp.dispatch("resolutionChanged"));
  }
}
const Y = 0.35, j = 0.6, Q = 0.4, J = 0.5;
function tt(r, t) {
  return r * t / (1 - t);
}
class it {
  /**
   * @param {Gestures} gestures
   */
  constructor(t) {
    this.gestures = t, this.pswp = t.pswp, this.startPan = {
      x: 0,
      y: 0
    };
  }
  start() {
    this.pswp.currSlide && p(this.startPan, this.pswp.currSlide.pan), this.pswp.animations.stopAll();
  }
  change() {
    const {
      p1: t,
      prevP1: i,
      dragAxis: e
    } = this.gestures, {
      currSlide: s
    } = this.pswp;
    if (e === "y" && this.pswp.options.closeOnVerticalDrag && s && s.currZoomLevel <= s.zoomLevels.fit && !this.gestures.isMultitouch) {
      const n = s.pan.y + (t.y - i.y);
      if (!this.pswp.dispatch("verticalDrag", {
        panY: n
      }).defaultPrevented) {
        this._setPanWithFriction("y", n, j);
        const o = 1 - Math.abs(this._getVerticalDragRatio(s.pan.y));
        this.pswp.applyBgOpacity(o), s.applyCurrentZoomPan();
      }
    } else
      this._panOrMoveMainScroll("x") || (this._panOrMoveMainScroll("y"), s && (Z(s.pan), s.applyCurrentZoomPan()));
  }
  end() {
    const {
      velocity: t
    } = this.gestures, {
      mainScroll: i,
      currSlide: e
    } = this.pswp;
    let s = 0;
    if (this.pswp.animations.stopAll(), i.isShifted()) {
      const o = (i.x - i.getCurrSlideX()) / this.pswp.viewportSize.x;
      t.x < -0.5 && o < 0 || t.x < 0.1 && o < -0.5 ? (s = 1, t.x = Math.min(t.x, 0)) : (t.x > J && o > 0 || t.x > -0.1 && o > 0.5) && (s = -1, t.x = Math.max(t.x, 0)), i.moveIndexBy(s, !0, t.x);
    }
    e && e.currZoomLevel > e.zoomLevels.max || this.gestures.isMultitouch ? this.gestures.zoomLevels.correctZoomPan(!0) : (this._finishPanGestureForAxis("x"), this._finishPanGestureForAxis("y"));
  }
  /**
   * @private
   * @param {'x' | 'y'} axis
   */
  _finishPanGestureForAxis(t) {
    const {
      velocity: i
    } = this.gestures, {
      currSlide: e
    } = this.pswp;
    if (!e)
      return;
    const {
      pan: s,
      bounds: n
    } = e, o = s[t], a = this.pswp.bgOpacity < 1 && t === "y", l = o + tt(i[t], 0.995);
    if (a) {
      const v = this._getVerticalDragRatio(o), w = this._getVerticalDragRatio(l);
      if (v < 0 && w < -0.4 || v > 0 && w > Q) {
        this.pswp.close();
        return;
      }
    }
    const c = n.correctPan(t, l);
    if (o === c)
      return;
    const d = c === l ? 1 : 0.82, u = this.pswp.bgOpacity, m = c - o;
    this.pswp.animations.startSpring({
      name: "panGesture" + t,
      isPan: !0,
      start: o,
      end: c,
      velocity: i[t],
      dampingRatio: d,
      onUpdate: (v) => {
        if (a && this.pswp.bgOpacity < 1) {
          const w = 1 - (c - v) / m;
          this.pswp.applyBgOpacity(b(u + (1 - u) * w, 0, 1));
        }
        s[t] = Math.floor(v), e.applyCurrentZoomPan();
      }
    });
  }
  /**
   * Update position of the main scroll,
   * or/and update pan position of the current slide.
   *
   * Should return true if it changes (or can change) main scroll.
   *
   * @private
   * @param {'x' | 'y'} axis
   * @returns {boolean}
   */
  _panOrMoveMainScroll(t) {
    const {
      p1: i,
      dragAxis: e,
      prevP1: s,
      isMultitouch: n
    } = this.gestures, {
      currSlide: o,
      mainScroll: a
    } = this.pswp, h = i[t] - s[t], l = a.x + h;
    if (!h || !o)
      return !1;
    if (t === "x" && !o.isPannable() && !n)
      return a.moveTo(l, !0), !0;
    const {
      bounds: c
    } = o, d = o.pan[t] + h;
    if (this.pswp.options.allowPanToNext && e === "x" && t === "x" && !n) {
      const u = a.getCurrSlideX(), m = a.x - u, v = h > 0, w = !v;
      if (d > c.min[t] && v) {
        if (c.min[t] <= this.startPan[t])
          return a.moveTo(l, !0), !0;
        this._setPanWithFriction(t, d);
      } else if (d < c.max[t] && w) {
        if (this.startPan[t] <= c.max[t])
          return a.moveTo(l, !0), !0;
        this._setPanWithFriction(t, d);
      } else if (m !== 0) {
        if (m > 0)
          return a.moveTo(Math.max(l, u), !0), !0;
        if (m < 0)
          return a.moveTo(Math.min(l, u), !0), !0;
      } else
        this._setPanWithFriction(t, d);
    } else
      t === "y" ? !a.isShifted() && c.min.y !== c.max.y && this._setPanWithFriction(t, d) : this._setPanWithFriction(t, d);
    return !1;
  }
  // If we move above - the ratio is negative
  // If we move below the ratio is positive
  /**
   * Relation between pan Y position and third of viewport height.
   *
   * When we are at initial position (center bounds) - the ratio is 0,
   * if position is shifted upwards - the ratio is negative,
   * if position is shifted downwards - the ratio is positive.
   *
   * @private
   * @param {number} panY The current pan Y position.
   * @returns {number}
   */
  _getVerticalDragRatio(t) {
    var i, e;
    return (t - ((i = (e = this.pswp.currSlide) === null || e === void 0 ? void 0 : e.bounds.center.y) !== null && i !== void 0 ? i : 0)) / (this.pswp.viewportSize.y / 3);
  }
  /**
   * Set pan position of the current slide.
   * Apply friction if the position is beyond the pan bounds,
   * or if custom friction is defined.
   *
   * @private
   * @param {'x' | 'y'} axis
   * @param {number} potentialPan
   * @param {number} [customFriction] (0.1 - 1)
   */
  _setPanWithFriction(t, i, e) {
    const {
      currSlide: s
    } = this.pswp;
    if (!s)
      return;
    const {
      pan: n,
      bounds: o
    } = s;
    if (o.correctPan(t, i) !== i || e) {
      const h = Math.round(i - n[t]);
      n[t] += h * (e || Y);
    } else
      n[t] = i;
  }
}
const et = 0.05, st = 0.15;
function z(r, t, i) {
  return r.x = (t.x + i.x) / 2, r.y = (t.y + i.y) / 2, r;
}
class nt {
  /**
   * @param {Gestures} gestures
   */
  constructor(t) {
    this.gestures = t, this._startPan = {
      x: 0,
      y: 0
    }, this._startZoomPoint = {
      x: 0,
      y: 0
    }, this._zoomPoint = {
      x: 0,
      y: 0
    }, this._wasOverFitZoomLevel = !1, this._startZoomLevel = 1;
  }
  start() {
    const {
      currSlide: t
    } = this.gestures.pswp;
    t && (this._startZoomLevel = t.currZoomLevel, p(this._startPan, t.pan)), this.gestures.pswp.animations.stopAllPan(), this._wasOverFitZoomLevel = !1;
  }
  change() {
    const {
      p1: t,
      startP1: i,
      p2: e,
      startP2: s,
      pswp: n
    } = this.gestures, {
      currSlide: o
    } = n;
    if (!o)
      return;
    const a = o.zoomLevels.min, h = o.zoomLevels.max;
    if (!o.isZoomable() || n.mainScroll.isShifted())
      return;
    z(this._startZoomPoint, i, s), z(this._zoomPoint, t, e);
    let l = 1 / A(i, s) * A(t, e) * this._startZoomLevel;
    if (l > o.zoomLevels.initial + o.zoomLevels.initial / 15 && (this._wasOverFitZoomLevel = !0), l < a)
      if (n.options.pinchToClose && !this._wasOverFitZoomLevel && this._startZoomLevel <= o.zoomLevels.initial) {
        const c = 1 - (a - l) / (a / 1.2);
        n.dispatch("pinchClose", {
          bgOpacity: c
        }).defaultPrevented || n.applyBgOpacity(c);
      } else
        l = a - (a - l) * st;
    else l > h && (l = h + (l - h) * et);
    o.pan.x = this._calculatePanForZoomLevel("x", l), o.pan.y = this._calculatePanForZoomLevel("y", l), o.setZoomLevel(l), o.applyCurrentZoomPan();
  }
  end() {
    const {
      pswp: t
    } = this.gestures, {
      currSlide: i
    } = t;
    (!i || i.currZoomLevel < i.zoomLevels.initial) && !this._wasOverFitZoomLevel && t.options.pinchToClose ? t.close() : this.correctZoomPan();
  }
  /**
   * @private
   * @param {'x' | 'y'} axis
   * @param {number} currZoomLevel
   * @returns {number}
   */
  _calculatePanForZoomLevel(t, i) {
    const e = i / this._startZoomLevel;
    return this._zoomPoint[t] - (this._startZoomPoint[t] - this._startPan[t]) * e;
  }
  /**
   * Correct currZoomLevel and pan if they are
   * beyond minimum or maximum values.
   * With animation.
   *
   * @param {boolean} [ignoreGesture]
   * Wether gesture coordinates should be ignored when calculating destination pan position.
   */
  correctZoomPan(t) {
    const {
      pswp: i
    } = this.gestures, {
      currSlide: e
    } = i;
    if (!(e != null && e.isZoomable()))
      return;
    this._zoomPoint.x === 0 && (t = !0);
    const s = e.currZoomLevel;
    let n, o = !0;
    s < e.zoomLevels.initial ? n = e.zoomLevels.initial : s > e.zoomLevels.max ? n = e.zoomLevels.max : (o = !1, n = s);
    const a = i.bgOpacity, h = i.bgOpacity < 1, l = p({
      x: 0,
      y: 0
    }, e.pan);
    let c = p({
      x: 0,
      y: 0
    }, l);
    t && (this._zoomPoint.x = 0, this._zoomPoint.y = 0, this._startZoomPoint.x = 0, this._startZoomPoint.y = 0, this._startZoomLevel = s, p(this._startPan, l)), o && (c = {
      x: this._calculatePanForZoomLevel("x", n),
      y: this._calculatePanForZoomLevel("y", n)
    }), e.setZoomLevel(n), c = {
      x: e.bounds.correctPan("x", c.x),
      y: e.bounds.correctPan("y", c.y)
    }, e.setZoomLevel(s);
    const d = !x(c, l);
    if (!d && !o && !h) {
      e._setResolution(n), e.applyCurrentZoomPan();
      return;
    }
    i.animations.stopAllPan(), i.animations.startSpring({
      isPan: !0,
      start: 0,
      end: 1e3,
      velocity: 0,
      dampingRatio: 1,
      naturalFrequency: 40,
      onUpdate: (u) => {
        if (u /= 1e3, d || o) {
          if (d && (e.pan.x = l.x + (c.x - l.x) * u, e.pan.y = l.y + (c.y - l.y) * u), o) {
            const m = s + (n - s) * u;
            e.setZoomLevel(m);
          }
          e.applyCurrentZoomPan();
        }
        h && i.bgOpacity < 1 && i.applyBgOpacity(b(a + (1 - a) * u, 0, 1));
      },
      onComplete: () => {
        e._setResolution(n), e.applyCurrentZoomPan();
      }
    });
  }
}
function E(r) {
  return !!/** @type {HTMLElement} */
  r.target.closest(".pswp__container");
}
class ot {
  /**
   * @param {Gestures} gestures
   */
  constructor(t) {
    this.gestures = t;
  }
  /**
   * @param {Point} point
   * @param {PointerEvent} originalEvent
   */
  click(t, i) {
    const e = (
      /** @type {HTMLElement} */
      i.target.classList
    ), s = e.contains("pswp__img"), n = e.contains("pswp__item") || e.contains("pswp__zoom-wrap");
    s ? this._doClickOrTapAction("imageClick", t, i) : n && this._doClickOrTapAction("bgClick", t, i);
  }
  /**
   * @param {Point} point
   * @param {PointerEvent} originalEvent
   */
  tap(t, i) {
    E(i) && this._doClickOrTapAction("tap", t, i);
  }
  /**
   * @param {Point} point
   * @param {PointerEvent} originalEvent
   */
  doubleTap(t, i) {
    E(i) && this._doClickOrTapAction("doubleTap", t, i);
  }
  /**
   * @private
   * @param {Actions} actionName
   * @param {Point} point
   * @param {PointerEvent} originalEvent
   */
  _doClickOrTapAction(t, i, e) {
    var s;
    const {
      pswp: n
    } = this.gestures, {
      currSlide: o
    } = n, a = (
      /** @type {AddPostfix<Actions, 'Action'>} */
      t + "Action"
    ), h = n.options[a];
    if (!n.dispatch(a, {
      point: i,
      originalEvent: e
    }).defaultPrevented) {
      if (typeof h == "function") {
        h.call(n, i, e);
        return;
      }
      switch (h) {
        case "close":
        case "next":
          n[h]();
          break;
        case "zoom":
          o == null || o.toggleZoom(i);
          break;
        case "zoom-or-close":
          o != null && o.isZoomable() && o.zoomLevels.secondary !== o.zoomLevels.initial ? o.toggleZoom(i) : n.options.clickToCloseNonZoomable && n.close();
          break;
        case "toggle-controls":
          (s = this.gestures.pswp.element) === null || s === void 0 || s.classList.toggle("pswp--ui-visible");
          break;
      }
    }
  }
}
const rt = 10, at = 300, ht = 25;
class lt {
  /**
   * @param {PhotoSwipe} pswp
   */
  constructor(t) {
    this.pswp = t, this.dragAxis = null, this.p1 = {
      x: 0,
      y: 0
    }, this.p2 = {
      x: 0,
      y: 0
    }, this.prevP1 = {
      x: 0,
      y: 0
    }, this.prevP2 = {
      x: 0,
      y: 0
    }, this.startP1 = {
      x: 0,
      y: 0
    }, this.startP2 = {
      x: 0,
      y: 0
    }, this.velocity = {
      x: 0,
      y: 0
    }, this._lastStartP1 = {
      x: 0,
      y: 0
    }, this._intervalP1 = {
      x: 0,
      y: 0
    }, this._numActivePoints = 0, this._ongoingPointers = [], this._touchEventEnabled = "ontouchstart" in window, this._pointerEventEnabled = !!window.PointerEvent, this.supportsTouch = this._touchEventEnabled || this._pointerEventEnabled && navigator.maxTouchPoints > 1, this._numActivePoints = 0, this._intervalTime = 0, this._velocityCalculated = !1, this.isMultitouch = !1, this.isDragging = !1, this.isZooming = !1, this.raf = null, this._tapTimer = null, this.supportsTouch || (t.options.allowPanToNext = !1), this.drag = new it(this), this.zoomLevels = new nt(this), this.tapHandler = new ot(this), t.on("bindEvents", () => {
      t.events.add(
        t.scrollWrap,
        "click",
        /** @type EventListener */
        this._onClick.bind(this)
      ), this._pointerEventEnabled ? this._bindEvents("pointer", "down", "up", "cancel") : this._touchEventEnabled ? (this._bindEvents("touch", "start", "end", "cancel"), t.scrollWrap && (t.scrollWrap.ontouchmove = () => {
      }, t.scrollWrap.ontouchend = () => {
      })) : this._bindEvents("mouse", "down", "up");
    });
  }
  /**
   * @private
   * @param {'mouse' | 'touch' | 'pointer'} pref
   * @param {'down' | 'start'} down
   * @param {'up' | 'end'} up
   * @param {'cancel'} [cancel]
   */
  _bindEvents(t, i, e, s) {
    const {
      pswp: n
    } = this, {
      events: o
    } = n, a = s ? t + s : "";
    o.add(
      n.scrollWrap,
      t + i,
      /** @type EventListener */
      this.onPointerDown.bind(this)
    ), o.add(
      window,
      t + "move",
      /** @type EventListener */
      this.onPointerMove.bind(this)
    ), o.add(
      window,
      t + e,
      /** @type EventListener */
      this.onPointerUp.bind(this)
    ), a && o.add(
      n.scrollWrap,
      a,
      /** @type EventListener */
      this.onPointerUp.bind(this)
    );
  }
  /**
   * @param {PointerEvent} e
   */
  onPointerDown(t) {
    const i = t.type === "mousedown" || t.pointerType === "mouse";
    if (i && t.button > 0)
      return;
    const {
      pswp: e
    } = this;
    if (!e.opener.isOpen) {
      t.preventDefault();
      return;
    }
    e.dispatch("pointerDown", {
      originalEvent: t
    }).defaultPrevented || (i && (e.mouseDetected(), this._preventPointerEventBehaviour(t, "down")), e.animations.stopAll(), this._updatePoints(t, "down"), this._numActivePoints === 1 && (this.dragAxis = null, p(this.startP1, this.p1)), this._numActivePoints > 1 ? (this._clearTapTimer(), this.isMultitouch = !0) : this.isMultitouch = !1);
  }
  /**
   * @param {PointerEvent} e
   */
  onPointerMove(t) {
    this._preventPointerEventBehaviour(t, "move"), this._numActivePoints && (this._updatePoints(t, "move"), !this.pswp.dispatch("pointerMove", {
      originalEvent: t
    }).defaultPrevented && (this._numActivePoints === 1 && !this.isDragging ? (this.dragAxis || this._calculateDragDirection(), this.dragAxis && !this.isDragging && (this.isZooming && (this.isZooming = !1, this.zoomLevels.end()), this.isDragging = !0, this._clearTapTimer(), this._updateStartPoints(), this._intervalTime = Date.now(), this._velocityCalculated = !1, p(this._intervalP1, this.p1), this.velocity.x = 0, this.velocity.y = 0, this.drag.start(), this._rafStopLoop(), this._rafRenderLoop())) : this._numActivePoints > 1 && !this.isZooming && (this._finishDrag(), this.isZooming = !0, this._updateStartPoints(), this.zoomLevels.start(), this._rafStopLoop(), this._rafRenderLoop())));
  }
  /**
   * @private
   */
  _finishDrag() {
    this.isDragging && (this.isDragging = !1, this._velocityCalculated || this._updateVelocity(!0), this.drag.end(), this.dragAxis = null);
  }
  /**
   * @param {PointerEvent} e
   */
  onPointerUp(t) {
    this._numActivePoints && (this._updatePoints(t, "up"), !this.pswp.dispatch("pointerUp", {
      originalEvent: t
    }).defaultPrevented && (this._numActivePoints === 0 && (this._rafStopLoop(), this.isDragging ? this._finishDrag() : !this.isZooming && !this.isMultitouch && this._finishTap(t)), this._numActivePoints < 2 && this.isZooming && (this.isZooming = !1, this.zoomLevels.end(), this._numActivePoints === 1 && (this.dragAxis = null, this._updateStartPoints()))));
  }
  /**
   * @private
   */
  _rafRenderLoop() {
    (this.isDragging || this.isZooming) && (this._updateVelocity(), this.isDragging ? x(this.p1, this.prevP1) || this.drag.change() : (!x(this.p1, this.prevP1) || !x(this.p2, this.prevP2)) && this.zoomLevels.change(), this._updatePrevPoints(), this.raf = requestAnimationFrame(this._rafRenderLoop.bind(this)));
  }
  /**
   * Update velocity at 50ms interval
   *
   * @private
   * @param {boolean} [force]
   */
  _updateVelocity(t) {
    const i = Date.now(), e = i - this._intervalTime;
    e < 50 && !t || (this.velocity.x = this._getVelocity("x", e), this.velocity.y = this._getVelocity("y", e), this._intervalTime = i, p(this._intervalP1, this.p1), this._velocityCalculated = !0);
  }
  /**
   * @private
   * @param {PointerEvent} e
   */
  _finishTap(t) {
    const {
      mainScroll: i
    } = this.pswp;
    if (i.isShifted()) {
      i.moveIndexBy(0, !0);
      return;
    }
    if (t.type.indexOf("cancel") > 0)
      return;
    if (t.type === "mouseup" || t.pointerType === "mouse") {
      this.tapHandler.click(this.startP1, t);
      return;
    }
    const e = this.pswp.options.doubleTapAction ? at : 0;
    this._tapTimer ? (this._clearTapTimer(), A(this._lastStartP1, this.startP1) < ht && this.tapHandler.doubleTap(this.startP1, t)) : (p(this._lastStartP1, this.startP1), this._tapTimer = setTimeout(() => {
      this.tapHandler.tap(this.startP1, t), this._clearTapTimer();
    }, e));
  }
  /**
   * @private
   */
  _clearTapTimer() {
    this._tapTimer && (clearTimeout(this._tapTimer), this._tapTimer = null);
  }
  /**
   * Get velocity for axis
   *
   * @private
   * @param {'x' | 'y'} axis
   * @param {number} duration
   * @returns {number}
   */
  _getVelocity(t, i) {
    const e = this.p1[t] - this._intervalP1[t];
    return Math.abs(e) > 1 && i > 5 ? e / i : 0;
  }
  /**
   * @private
   */
  _rafStopLoop() {
    this.raf && (cancelAnimationFrame(this.raf), this.raf = null);
  }
  /**
   * @private
   * @param {PointerEvent} e
   * @param {'up' | 'down' | 'move'} pointerType Normalized pointer type
   */
  _preventPointerEventBehaviour(t, i) {
    this.pswp.applyFilters("preventPointerEvent", !0, t, i) && t.preventDefault();
  }
  /**
   * Parses and normalizes points from the touch, mouse or pointer event.
   * Updates p1 and p2.
   *
   * @private
   * @param {PointerEvent | TouchEvent} e
   * @param {'up' | 'down' | 'move'} pointerType Normalized pointer type
   */
  _updatePoints(t, i) {
    if (this._pointerEventEnabled) {
      const e = (
        /** @type {PointerEvent} */
        t
      ), s = this._ongoingPointers.findIndex((n) => n.id === e.pointerId);
      i === "up" && s > -1 ? this._ongoingPointers.splice(s, 1) : i === "down" && s === -1 ? this._ongoingPointers.push(this._convertEventPosToPoint(e, {
        x: 0,
        y: 0
      })) : s > -1 && this._convertEventPosToPoint(e, this._ongoingPointers[s]), this._numActivePoints = this._ongoingPointers.length, this._numActivePoints > 0 && p(this.p1, this._ongoingPointers[0]), this._numActivePoints > 1 && p(this.p2, this._ongoingPointers[1]);
    } else {
      const e = (
        /** @type {TouchEvent} */
        t
      );
      this._numActivePoints = 0, e.type.indexOf("touch") > -1 ? e.touches && e.touches.length > 0 && (this._convertEventPosToPoint(e.touches[0], this.p1), this._numActivePoints++, e.touches.length > 1 && (this._convertEventPosToPoint(e.touches[1], this.p2), this._numActivePoints++)) : (this._convertEventPosToPoint(
        /** @type {PointerEvent} */
        t,
        this.p1
      ), i === "up" ? this._numActivePoints = 0 : this._numActivePoints++);
    }
  }
  /** update points that were used during previous rAF tick
   * @private
   */
  _updatePrevPoints() {
    p(this.prevP1, this.p1), p(this.prevP2, this.p2);
  }
  /** update points at the start of gesture
   * @private
   */
  _updateStartPoints() {
    p(this.startP1, this.p1), p(this.startP2, this.p2), this._updatePrevPoints();
  }
  /** @private */
  _calculateDragDirection() {
    if (this.pswp.mainScroll.isShifted())
      this.dragAxis = "x";
    else {
      const t = Math.abs(this.p1.x - this.startP1.x) - Math.abs(this.p1.y - this.startP1.y);
      if (t !== 0) {
        const i = t > 0 ? "x" : "y";
        Math.abs(this.p1[i] - this.startP1[i]) >= rt && (this.dragAxis = i);
      }
    }
  }
  /**
   * Converts touch, pointer or mouse event
   * to PhotoSwipe point.
   *
   * @private
   * @param {Touch | PointerEvent} e
   * @param {Point} p
   * @returns {Point}
   */
  _convertEventPosToPoint(t, i) {
    return i.x = t.pageX - this.pswp.offset.x, i.y = t.pageY - this.pswp.offset.y, "pointerId" in t ? i.id = t.pointerId : t.identifier !== void 0 && (i.id = t.identifier), i;
  }
  /**
   * @private
   * @param {PointerEvent} e
   */
  _onClick(t) {
    this.pswp.mainScroll.isShifted() && (t.preventDefault(), t.stopPropagation());
  }
}
const ct = 0.35;
class dt {
  /**
   * @param {PhotoSwipe} pswp
   */
  constructor(t) {
    this.pswp = t, this.x = 0, this.slideWidth = 0, this._currPositionIndex = 0, this._prevPositionIndex = 0, this._containerShiftIndex = -1, this.itemHolders = [];
  }
  /**
   * Position the scroller and slide containers
   * according to viewport size.
   *
   * @param {boolean} [resizeSlides] Whether slides content should resized
   */
  resize(t) {
    const {
      pswp: i
    } = this, e = Math.round(i.viewportSize.x + i.viewportSize.x * i.options.spacing), s = e !== this.slideWidth;
    s && (this.slideWidth = e, this.moveTo(this.getCurrSlideX())), this.itemHolders.forEach((n, o) => {
      s && y(n.el, (o + this._containerShiftIndex) * this.slideWidth), t && n.slide && n.slide.resize();
    });
  }
  /**
   * Reset X position of the main scroller to zero
   */
  resetPosition() {
    this._currPositionIndex = 0, this._prevPositionIndex = 0, this.slideWidth = 0, this._containerShiftIndex = -1;
  }
  /**
   * Create and append array of three items
   * that hold data about slides in DOM
   */
  appendHolders() {
    this.itemHolders = [];
    for (let t = 0; t < 3; t++) {
      const i = f("pswp__item", "div", this.pswp.container);
      i.setAttribute("role", "group"), i.setAttribute("aria-roledescription", "slide"), i.setAttribute("aria-hidden", "true"), i.style.display = t === 1 ? "block" : "none", this.itemHolders.push({
        el: i
        //index: -1
      });
    }
  }
  /**
   * Whether the main scroll can be horizontally swiped to the next or previous slide.
   * @returns {boolean}
   */
  canBeSwiped() {
    return this.pswp.getNumItems() > 1;
  }
  /**
   * Move main scroll by X amount of slides.
   * For example:
   *   `-1` will move to the previous slide,
   *    `0` will reset the scroll position of the current slide,
   *    `3` will move three slides forward
   *
   * If loop option is enabled - index will be automatically looped too,
   * (for example `-1` will move to the last slide of the gallery).
   *
   * @param {number} diff
   * @param {boolean} [animate]
   * @param {number} [velocityX]
   * @returns {boolean} whether index was changed or not
   */
  moveIndexBy(t, i, e) {
    const {
      pswp: s
    } = this;
    let n = s.potentialIndex + t;
    const o = s.getNumItems();
    if (s.canLoop()) {
      n = s.getLoopedIndex(n);
      const h = (t + o) % o;
      h <= o / 2 ? t = h : t = h - o;
    } else
      n < 0 ? n = 0 : n >= o && (n = o - 1), t = n - s.potentialIndex;
    s.potentialIndex = n, this._currPositionIndex -= t, s.animations.stopMainScroll();
    const a = this.getCurrSlideX();
    if (!i)
      this.moveTo(a), this.updateCurrItem();
    else {
      s.animations.startSpring({
        isMainScroll: !0,
        start: this.x,
        end: a,
        velocity: e || 0,
        naturalFrequency: 30,
        dampingRatio: 1,
        //0.7,
        onUpdate: (l) => {
          this.moveTo(l);
        },
        onComplete: () => {
          this.updateCurrItem(), s.appendHeavy();
        }
      });
      let h = s.potentialIndex - s.currIndex;
      if (s.canLoop()) {
        const l = (h + o) % o;
        l <= o / 2 ? h = l : h = l - o;
      }
      Math.abs(h) > 1 && this.updateCurrItem();
    }
    return !!t;
  }
  /**
   * X position of the main scroll for the current slide
   * (ignores position during dragging)
   * @returns {number}
   */
  getCurrSlideX() {
    return this.slideWidth * this._currPositionIndex;
  }
  /**
   * Whether scroll position is shifted.
   * For example, it will return true if the scroll is being dragged or animated.
   * @returns {boolean}
   */
  isShifted() {
    return this.x !== this.getCurrSlideX();
  }
  /**
   * Update slides X positions and set their content
   */
  updateCurrItem() {
    var t;
    const {
      pswp: i
    } = this, e = this._prevPositionIndex - this._currPositionIndex;
    if (!e)
      return;
    this._prevPositionIndex = this._currPositionIndex, i.currIndex = i.potentialIndex;
    let s = Math.abs(e), n;
    s >= 3 && (this._containerShiftIndex += e + (e > 0 ? -3 : 3), s = 3, this.itemHolders.forEach((o) => {
      var a;
      (a = o.slide) === null || a === void 0 || a.destroy(), o.slide = void 0;
    }));
    for (let o = 0; o < s; o++)
      e > 0 ? (n = this.itemHolders.shift(), n && (this.itemHolders[2] = n, this._containerShiftIndex++, y(n.el, (this._containerShiftIndex + 2) * this.slideWidth), i.setContent(n, i.currIndex - s + o + 2))) : (n = this.itemHolders.pop(), n && (this.itemHolders.unshift(n), this._containerShiftIndex--, y(n.el, this._containerShiftIndex * this.slideWidth), i.setContent(n, i.currIndex + s - o - 2)));
    Math.abs(this._containerShiftIndex) > 50 && !this.isShifted() && (this.resetPosition(), this.resize()), i.animations.stopAllPan(), this.itemHolders.forEach((o, a) => {
      o.slide && o.slide.setIsActive(a === 1);
    }), i.currSlide = (t = this.itemHolders[1]) === null || t === void 0 ? void 0 : t.slide, i.contentLoader.updateLazy(e), i.currSlide && i.currSlide.applyCurrentZoomPan(), i.dispatch("change");
  }
  /**
   * Move the X position of the main scroll container
   *
   * @param {number} x
   * @param {boolean} [dragging]
   */
  moveTo(t, i) {
    if (!this.pswp.canLoop() && i) {
      let e = (this.slideWidth * this._currPositionIndex - t) / this.slideWidth;
      e += this.pswp.currIndex;
      const s = Math.round(t - this.x);
      (e < 0 && s > 0 || e >= this.pswp.getNumItems() - 1 && s < 0) && (t = this.x + s * ct);
    }
    this.x = t, this.pswp.container && y(this.pswp.container, t), this.pswp.dispatch("moveMainScroll", {
      x: t,
      dragging: i ?? !1
    });
  }
}
const pt = {
  Escape: 27,
  z: 90,
  ArrowLeft: 37,
  ArrowUp: 38,
  ArrowRight: 39,
  ArrowDown: 40,
  Tab: 9
}, g = (r, t) => t ? r : pt[r];
class ut {
  /**
   * @param {PhotoSwipe} pswp
   */
  constructor(t) {
    this.pswp = t, this._wasFocused = !1, t.on("bindEvents", () => {
      t.options.trapFocus && (t.options.initialPointerPos || this._focusRoot(), t.events.add(
        document,
        "focusin",
        /** @type EventListener */
        this._onFocusIn.bind(this)
      )), t.events.add(
        document,
        "keydown",
        /** @type EventListener */
        this._onKeyDown.bind(this)
      );
    });
    const i = (
      /** @type {HTMLElement} */
      document.activeElement
    );
    t.on("destroy", () => {
      t.options.returnFocus && i && this._wasFocused && i.focus();
    });
  }
  /** @private */
  _focusRoot() {
    !this._wasFocused && this.pswp.element && (this.pswp.element.focus(), this._wasFocused = !0);
  }
  /**
   * @private
   * @param {KeyboardEvent} e
   */
  _onKeyDown(t) {
    const {
      pswp: i
    } = this;
    if (i.dispatch("keydown", {
      originalEvent: t
    }).defaultPrevented || U(t))
      return;
    let e, s, n = !1;
    const o = "key" in t;
    switch (o ? t.key : t.keyCode) {
      case g("Escape", o):
        i.options.escKey && (e = "close");
        break;
      case g("z", o):
        e = "toggleZoom";
        break;
      case g("ArrowLeft", o):
        s = "x";
        break;
      case g("ArrowUp", o):
        s = "y";
        break;
      case g("ArrowRight", o):
        s = "x", n = !0;
        break;
      case g("ArrowDown", o):
        n = !0, s = "y";
        break;
      case g("Tab", o):
        this._focusRoot();
        break;
    }
    if (s) {
      t.preventDefault();
      const {
        currSlide: a
      } = i;
      i.options.arrowKeys && s === "x" && i.getNumItems() > 1 ? e = n ? "next" : "prev" : a && a.currZoomLevel > a.zoomLevels.fit && (a.pan[s] += n ? -80 : 80, a.panTo(a.pan.x, a.pan.y));
    }
    e && (t.preventDefault(), i[e]());
  }
  /**
   * Trap focus inside photoswipe
   *
   * @private
   * @param {FocusEvent} e
   */
  _onFocusIn(t) {
    const {
      template: i
    } = this.pswp;
    i && document !== t.target && i !== t.target && !i.contains(
      /** @type {Node} */
      t.target
    ) && i.focus();
  }
}
const mt = "cubic-bezier(.4,0,.22,1)";
class ft {
  /**
   * onComplete can be unpredictable, be careful about current state
   *
   * @param {CssAnimationProps} props
   */
  constructor(t) {
    var i;
    this.props = t;
    const {
      target: e,
      onComplete: s,
      transform: n,
      onFinish: o = () => {
      },
      duration: a = 333,
      easing: h = mt
    } = t;
    this.onFinish = o;
    const l = n ? "transform" : "opacity", c = (i = t[l]) !== null && i !== void 0 ? i : "";
    this._target = e, this._onComplete = s, this._finished = !1, this._onTransitionEnd = this._onTransitionEnd.bind(this), this._helperTimeout = setTimeout(() => {
      D(e, l, a, h), this._helperTimeout = setTimeout(() => {
        e.addEventListener("transitionend", this._onTransitionEnd, !1), e.addEventListener("transitioncancel", this._onTransitionEnd, !1), this._helperTimeout = setTimeout(() => {
          this._finalizeAnimation();
        }, a + 500), e.style[l] = c;
      }, 30);
    }, 0);
  }
  /**
   * @private
   * @param {TransitionEvent} e
   */
  _onTransitionEnd(t) {
    t.target === this._target && this._finalizeAnimation();
  }
  /**
   * @private
   */
  _finalizeAnimation() {
    this._finished || (this._finished = !0, this.onFinish(), this._onComplete && this._onComplete());
  }
  // Destroy is called automatically onFinish
  destroy() {
    this._helperTimeout && clearTimeout(this._helperTimeout), V(this._target), this._target.removeEventListener("transitionend", this._onTransitionEnd, !1), this._target.removeEventListener("transitioncancel", this._onTransitionEnd, !1), this._finished || this._finalizeAnimation();
  }
}
const _t = 12, vt = 0.75;
class gt {
  /**
   * @param {number} initialVelocity Initial velocity, px per ms.
   *
   * @param {number} [dampingRatio]
   * Determines how bouncy animation will be.
   * From 0 to 1, 0 - always overshoot, 1 - do not overshoot.
   * "overshoot" refers to part of animation that
   * goes beyond the final value.
   *
   * @param {number} [naturalFrequency]
   * Determines how fast animation will slow down.
   * The higher value - the stiffer the transition will be,
   * and the faster it will slow down.
   * Recommended value from 10 to 50
   */
  constructor(t, i, e) {
    this.velocity = t * 1e3, this._dampingRatio = i || vt, this._naturalFrequency = e || _t, this._dampedFrequency = this._naturalFrequency, this._dampingRatio < 1 && (this._dampedFrequency *= Math.sqrt(1 - this._dampingRatio * this._dampingRatio));
  }
  /**
   * @param {number} deltaPosition Difference between current and end position of the animation
   * @param {number} deltaTime Frame duration in milliseconds
   *
   * @returns {number} Displacement, relative to the end position.
   */
  easeFrame(t, i) {
    let e = 0, s;
    i /= 1e3;
    const n = Math.E ** (-this._dampingRatio * this._naturalFrequency * i);
    if (this._dampingRatio === 1)
      s = this.velocity + this._naturalFrequency * t, e = (t + s * i) * n, this.velocity = e * -this._naturalFrequency + s * n;
    else if (this._dampingRatio < 1) {
      s = 1 / this._dampedFrequency * (this._dampingRatio * this._naturalFrequency * t + this.velocity);
      const o = Math.cos(this._dampedFrequency * i), a = Math.sin(this._dampedFrequency * i);
      e = n * (t * o + s * a), this.velocity = e * -this._naturalFrequency * this._dampingRatio + n * (-this._dampedFrequency * t * a + this._dampedFrequency * s * o);
    }
    return e;
  }
}
class yt {
  /**
   * @param {SpringAnimationProps} props
   */
  constructor(t) {
    this.props = t, this._raf = 0;
    const {
      start: i,
      end: e,
      velocity: s,
      onUpdate: n,
      onComplete: o,
      onFinish: a = () => {
      },
      dampingRatio: h,
      naturalFrequency: l
    } = t;
    this.onFinish = a;
    const c = new gt(s, h, l);
    let d = Date.now(), u = i - e;
    const m = () => {
      this._raf && (u = c.easeFrame(u, Date.now() - d), Math.abs(u) < 1 && Math.abs(c.velocity) < 50 ? (n(e), o && o(), this.onFinish()) : (d = Date.now(), n(u + e), this._raf = requestAnimationFrame(m)));
    };
    this._raf = requestAnimationFrame(m);
  }
  // Destroy is called automatically onFinish
  destroy() {
    this._raf >= 0 && cancelAnimationFrame(this._raf), this._raf = 0;
  }
}
class wt {
  constructor() {
    this.activeAnimations = [];
  }
  /**
   * @param {SpringAnimationProps} props
   */
  startSpring(t) {
    this._start(t, !0);
  }
  /**
   * @param {CssAnimationProps} props
   */
  startTransition(t) {
    this._start(t);
  }
  /**
   * @private
   * @param {AnimationProps} props
   * @param {boolean} [isSpring]
   * @returns {Animation}
   */
  _start(t, i) {
    const e = i ? new yt(
      /** @type SpringAnimationProps */
      t
    ) : new ft(
      /** @type CssAnimationProps */
      t
    );
    return this.activeAnimations.push(e), e.onFinish = () => this.stop(e), e;
  }
  /**
   * @param {Animation} animation
   */
  stop(t) {
    t.destroy();
    const i = this.activeAnimations.indexOf(t);
    i > -1 && this.activeAnimations.splice(i, 1);
  }
  stopAll() {
    this.activeAnimations.forEach((t) => {
      t.destroy();
    }), this.activeAnimations = [];
  }
  /**
   * Stop all pan or zoom transitions
   */
  stopAllPan() {
    this.activeAnimations = this.activeAnimations.filter((t) => t.props.isPan ? (t.destroy(), !1) : !0);
  }
  stopMainScroll() {
    this.activeAnimations = this.activeAnimations.filter((t) => t.props.isMainScroll ? (t.destroy(), !1) : !0);
  }
  /**
   * Returns true if main scroll transition is running
   */
  // isMainScrollRunning() {
  //   return this.activeAnimations.some((animation) => {
  //     return animation.props.isMainScroll;
  //   });
  // }
  /**
   * Returns true if any pan or zoom transition is running
   */
  isPanRunning() {
    return this.activeAnimations.some((t) => t.props.isPan);
  }
}
class Pt {
  /**
   * @param {PhotoSwipe} pswp
   */
  constructor(t) {
    this.pswp = t, t.events.add(
      t.element,
      "wheel",
      /** @type EventListener */
      this._onWheel.bind(this)
    );
  }
  /**
   * @private
   * @param {WheelEvent} e
   */
  _onWheel(t) {
    t.preventDefault();
    const {
      currSlide: i
    } = this.pswp;
    let {
      deltaX: e,
      deltaY: s
    } = t;
    if (i && !this.pswp.dispatch("wheel", {
      originalEvent: t
    }).defaultPrevented)
      if (t.ctrlKey || this.pswp.options.wheelToZoom) {
        if (i.isZoomable()) {
          let n = -s;
          t.deltaMode === 1 ? n *= 0.05 : n *= t.deltaMode ? 1 : 2e-3, n = 2 ** n;
          const o = i.currZoomLevel * n;
          i.zoomTo(o, {
            x: t.clientX,
            y: t.clientY
          });
        }
      } else
        i.isPannable() && (t.deltaMode === 1 && (e *= 18, s *= 18), i.panTo(i.pan.x - e, i.pan.y - s));
  }
}
function St(r) {
  if (typeof r == "string")
    return r;
  if (!r || !r.isCustomSVG)
    return "";
  const t = r;
  let i = '<svg aria-hidden="true" class="pswp__icn" viewBox="0 0 %d %d" width="%d" height="%d">';
  return i = i.split("%d").join(
    /** @type {string} */
    t.size || 32
  ), t.outlineID && (i += '<use class="pswp__icn-shadow" xlink:href="#' + t.outlineID + '"/>'), i += t.inner, i += "</svg>", i;
}
class xt {
  /**
   * @param {PhotoSwipe} pswp
   * @param {UIElementData} data
   */
  constructor(t, i) {
    var e;
    const s = i.name || i.className;
    let n = i.html;
    if (t.options[s] === !1)
      return;
    typeof t.options[s + "SVG"] == "string" && (n = t.options[s + "SVG"]), t.dispatch("uiElementCreate", {
      data: i
    });
    let o = "";
    i.isButton ? (o += "pswp__button ", o += i.className || `pswp__button--${i.name}`) : o += i.className || `pswp__${i.name}`;
    let a = i.isButton ? i.tagName || "button" : i.tagName || "div";
    a = /** @type {keyof HTMLElementTagNameMap} */
    a.toLowerCase();
    const h = f(o, a);
    if (i.isButton) {
      a === "button" && (h.type = "button");
      let {
        title: d
      } = i;
      const {
        ariaLabel: u
      } = i;
      typeof t.options[s + "Title"] == "string" && (d = t.options[s + "Title"]), d && (h.title = d);
      const m = u || d;
      m && h.setAttribute("aria-label", m);
    }
    h.innerHTML = St(n), i.onInit && i.onInit(h, t), i.onClick && (h.onclick = (d) => {
      typeof i.onClick == "string" ? t[i.onClick]() : typeof i.onClick == "function" && i.onClick(d, h, t);
    });
    const l = i.appendTo || "bar";
    let c = t.element;
    l === "bar" ? (t.topBar || (t.topBar = f("pswp__top-bar pswp__hide-on-close", "div", t.scrollWrap)), c = t.topBar) : (h.classList.add("pswp__hide-on-close"), l === "wrapper" && (c = t.scrollWrap)), (e = c) === null || e === void 0 || e.appendChild(t.applyFilters("uiElement", h, i));
  }
}
function N(r, t, i) {
  r.classList.add("pswp__button--arrow"), r.setAttribute("aria-controls", "pswp__items"), t.on("change", () => {
    t.options.loop || (i ? r.disabled = !(t.currIndex < t.getNumItems() - 1) : r.disabled = !(t.currIndex > 0));
  });
}
const It = {
  name: "arrowPrev",
  className: "pswp__button--arrow--prev",
  title: "Previous",
  order: 10,
  isButton: !0,
  appendTo: "wrapper",
  html: {
    isCustomSVG: !0,
    size: 60,
    inner: '<path d="M29 43l-3 3-16-16 16-16 3 3-13 13 13 13z" id="pswp__icn-arrow"/>',
    outlineID: "pswp__icn-arrow"
  },
  onClick: "prev",
  onInit: N
}, bt = {
  name: "arrowNext",
  className: "pswp__button--arrow--next",
  title: "Next",
  order: 11,
  isButton: !0,
  appendTo: "wrapper",
  html: {
    isCustomSVG: !0,
    size: 60,
    inner: '<use xlink:href="#pswp__icn-arrow"/>',
    outlineID: "pswp__icn-arrow"
  },
  onClick: "next",
  onInit: (r, t) => {
    N(r, t, !0);
  }
}, At = {
  name: "close",
  title: "Close",
  order: 20,
  isButton: !0,
  html: {
    isCustomSVG: !0,
    inner: '<path d="M24 10l-2-2-6 6-6-6-2 2 6 6-6 6 2 2 6-6 6 6 2-2-6-6z" id="pswp__icn-close"/>',
    outlineID: "pswp__icn-close"
  },
  onClick: "close"
}, Lt = {
  name: "zoom",
  title: "Zoom",
  order: 10,
  isButton: !0,
  html: {
    isCustomSVG: !0,
    // eslint-disable-next-line max-len
    inner: '<path d="M17.426 19.926a6 6 0 1 1 1.5-1.5L23 22.5 21.5 24l-4.074-4.074z" id="pswp__icn-zoom"/><path fill="currentColor" class="pswp__zoom-icn-bar-h" d="M11 16v-2h6v2z"/><path fill="currentColor" class="pswp__zoom-icn-bar-v" d="M13 12h2v6h-2z"/>',
    outlineID: "pswp__icn-zoom"
  },
  onClick: "toggleZoom"
}, Ct = {
  name: "preloader",
  appendTo: "bar",
  order: 7,
  html: {
    isCustomSVG: !0,
    // eslint-disable-next-line max-len
    inner: '<path fill-rule="evenodd" clip-rule="evenodd" d="M21.2 16a5.2 5.2 0 1 1-5.2-5.2V8a8 8 0 1 0 8 8h-2.8Z" id="pswp__icn-loading"/>',
    outlineID: "pswp__icn-loading"
  },
  onInit: (r, t) => {
    let i, e = null;
    const s = (a, h) => {
      r.classList.toggle("pswp__preloader--" + a, h);
    }, n = (a) => {
      i !== a && (i = a, s("active", a));
    }, o = () => {
      var a;
      if (!((a = t.currSlide) !== null && a !== void 0 && a.content.isLoading())) {
        n(!1), e && (clearTimeout(e), e = null);
        return;
      }
      e || (e = setTimeout(() => {
        var h;
        n(!!(!((h = t.currSlide) === null || h === void 0) && h.content.isLoading())), e = null;
      }, t.options.preloaderDelay));
    };
    t.on("change", o), t.on("loadComplete", (a) => {
      t.currSlide === a.slide && o();
    }), t.ui && (t.ui.updatePreloaderVisibility = o);
  }
}, Tt = {
  name: "counter",
  order: 5,
  onInit: (r, t) => {
    t.on("change", () => {
      r.innerText = t.currIndex + 1 + t.options.indexIndicatorSep + t.getNumItems();
    });
  }
};
function O(r, t) {
  r.classList.toggle("pswp--zoomed-in", t);
}
class zt {
  /**
   * @param {PhotoSwipe} pswp
   */
  constructor(t) {
    this.pswp = t, this.isRegistered = !1, this.uiElementsData = [], this.items = [], this.updatePreloaderVisibility = () => {
    }, this._lastUpdatedZoomLevel = void 0;
  }
  init() {
    const {
      pswp: t
    } = this;
    this.isRegistered = !1, this.uiElementsData = [At, It, bt, Lt, Ct, Tt], t.dispatch("uiRegister"), this.uiElementsData.sort((i, e) => (i.order || 0) - (e.order || 0)), this.items = [], this.isRegistered = !0, this.uiElementsData.forEach((i) => {
      this.registerElement(i);
    }), t.on("change", () => {
      var i;
      (i = t.element) === null || i === void 0 || i.classList.toggle("pswp--one-slide", t.getNumItems() === 1);
    }), t.on("zoomPanUpdate", () => this._onZoomPanUpdate());
  }
  /**
   * @param {UIElementData} elementData
   */
  registerElement(t) {
    this.isRegistered ? this.items.push(new xt(this.pswp, t)) : this.uiElementsData.push(t);
  }
  /**
   * Fired each time zoom or pan position is changed.
   * Update classes that control visibility of zoom button and cursor icon.
   *
   * @private
   */
  _onZoomPanUpdate() {
    const {
      template: t,
      currSlide: i,
      options: e
    } = this.pswp;
    if (this.pswp.opener.isClosing || !t || !i)
      return;
    let {
      currZoomLevel: s
    } = i;
    if (this.pswp.opener.isOpen || (s = i.zoomLevels.initial), s === this._lastUpdatedZoomLevel)
      return;
    this._lastUpdatedZoomLevel = s;
    const n = i.zoomLevels.initial - i.zoomLevels.secondary;
    if (Math.abs(n) < 0.01 || !i.isZoomable()) {
      O(t, !1), t.classList.remove("pswp--zoom-allowed");
      return;
    }
    t.classList.add("pswp--zoom-allowed");
    const o = s === i.zoomLevels.initial ? i.zoomLevels.secondary : i.zoomLevels.initial;
    O(t, o <= s), (e.imageClickAction === "zoom" || e.imageClickAction === "zoom-or-close") && t.classList.add("pswp--click-to-zoom");
  }
}
function Et(r) {
  const t = r.getBoundingClientRect();
  return {
    x: t.left,
    y: t.top,
    w: t.width
  };
}
function Ot(r, t, i) {
  const e = r.getBoundingClientRect(), s = e.width / t, n = e.height / i, o = s > n ? s : n, a = (e.width - t * o) / 2, h = (e.height - i * o) / 2, l = {
    x: e.left + a,
    y: e.top + h,
    w: t * o
  };
  return l.innerRect = {
    w: e.width,
    h: e.height,
    x: a,
    y: h
  }, l;
}
function Zt(r, t, i) {
  const e = i.dispatch("thumbBounds", {
    index: r,
    itemData: t,
    instance: i
  });
  if (e.thumbBounds)
    return e.thumbBounds;
  const {
    element: s
  } = t;
  let n, o;
  if (s && i.options.thumbSelector !== !1) {
    const a = i.options.thumbSelector || "img";
    o = s.matches(a) ? s : (
      /** @type {HTMLElement | null} */
      s.querySelector(a)
    );
  }
  return o = i.applyFilters("thumbEl", o, t, r), o && (t.thumbCropped ? n = Ot(o, t.width || t.w || 0, t.height || t.h || 0) : n = Et(o)), i.applyFilters("thumbBounds", n, t, r);
}
class Dt {
  /**
   * @param {T} type
   * @param {PhotoSwipeEventsMap[T]} [details]
   */
  constructor(t, i) {
    this.type = t, this.defaultPrevented = !1, i && Object.assign(this, i);
  }
  preventDefault() {
    this.defaultPrevented = !0;
  }
}
class Mt {
  constructor() {
    this._listeners = {}, this._filters = {}, this.pswp = void 0, this.options = void 0;
  }
  /**
   * @template {keyof PhotoSwipeFiltersMap} T
   * @param {T} name
   * @param {PhotoSwipeFiltersMap[T]} fn
   * @param {number} priority
   */
  addFilter(t, i, e = 100) {
    var s, n, o;
    this._filters[t] || (this._filters[t] = []), (s = this._filters[t]) === null || s === void 0 || s.push({
      fn: i,
      priority: e
    }), (n = this._filters[t]) === null || n === void 0 || n.sort((a, h) => a.priority - h.priority), (o = this.pswp) === null || o === void 0 || o.addFilter(t, i, e);
  }
  /**
   * @template {keyof PhotoSwipeFiltersMap} T
   * @param {T} name
   * @param {PhotoSwipeFiltersMap[T]} fn
   */
  removeFilter(t, i) {
    this._filters[t] && (this._filters[t] = this._filters[t].filter((e) => e.fn !== i)), this.pswp && this.pswp.removeFilter(t, i);
  }
  /**
   * @template {keyof PhotoSwipeFiltersMap} T
   * @param {T} name
   * @param {Parameters<PhotoSwipeFiltersMap[T]>} args
   * @returns {Parameters<PhotoSwipeFiltersMap[T]>[0]}
   */
  applyFilters(t, ...i) {
    var e;
    return (e = this._filters[t]) === null || e === void 0 || e.forEach((s) => {
      i[0] = s.fn.apply(this, i);
    }), i[0];
  }
  /**
   * @template {keyof PhotoSwipeEventsMap} T
   * @param {T} name
   * @param {EventCallback<T>} fn
   */
  on(t, i) {
    var e, s;
    this._listeners[t] || (this._listeners[t] = []), (e = this._listeners[t]) === null || e === void 0 || e.push(i), (s = this.pswp) === null || s === void 0 || s.on(t, i);
  }
  /**
   * @template {keyof PhotoSwipeEventsMap} T
   * @param {T} name
   * @param {EventCallback<T>} fn
   */
  off(t, i) {
    var e;
    this._listeners[t] && (this._listeners[t] = this._listeners[t].filter((s) => i !== s)), (e = this.pswp) === null || e === void 0 || e.off(t, i);
  }
  /**
   * @template {keyof PhotoSwipeEventsMap} T
   * @param {T} name
   * @param {PhotoSwipeEventsMap[T]} [details]
   * @returns {AugmentedEvent<T>}
   */
  dispatch(t, i) {
    var e;
    if (this.pswp)
      return this.pswp.dispatch(t, i);
    const s = (
      /** @type {AugmentedEvent<T>} */
      new Dt(t, i)
    );
    return (e = this._listeners[t]) === null || e === void 0 || e.forEach((n) => {
      n.call(this, s);
    }), s;
  }
}
class Rt {
  /**
   * @param {string | false} imageSrc
   * @param {HTMLElement} container
   */
  constructor(t, i) {
    if (this.element = f("pswp__img pswp__img--placeholder", t ? "img" : "div", i), t) {
      const e = (
        /** @type {HTMLImageElement} */
        this.element
      );
      e.decoding = "async", e.alt = "", e.src = t, e.setAttribute("role", "presentation");
    }
    this.element.setAttribute("aria-hidden", "true");
  }
  /**
   * @param {number} width
   * @param {number} height
   */
  setDisplayedSize(t, i) {
    this.element && (this.element.tagName === "IMG" ? (L(this.element, 250, "auto"), this.element.style.transformOrigin = "0 0", this.element.style.transform = I(0, 0, t / 250)) : L(this.element, t, i));
  }
  destroy() {
    var t;
    (t = this.element) !== null && t !== void 0 && t.parentNode && this.element.remove(), this.element = null;
  }
}
class Ft {
  /**
   * @param {SlideData} itemData Slide data
   * @param {PhotoSwipeBase} instance PhotoSwipe or PhotoSwipeLightbox instance
   * @param {number} index
   */
  constructor(t, i, e) {
    this.instance = i, this.data = t, this.index = e, this.element = void 0, this.placeholder = void 0, this.slide = void 0, this.displayedImageWidth = 0, this.displayedImageHeight = 0, this.width = Number(this.data.w) || Number(this.data.width) || 0, this.height = Number(this.data.h) || Number(this.data.height) || 0, this.isAttached = !1, this.hasSlide = !1, this.isDecoding = !1, this.state = _.IDLE, this.data.type ? this.type = this.data.type : this.data.src ? this.type = "image" : this.type = "html", this.instance.dispatch("contentInit", {
      content: this
    });
  }
  removePlaceholder() {
    this.placeholder && !this.keepPlaceholder() && setTimeout(() => {
      this.placeholder && (this.placeholder.destroy(), this.placeholder = void 0);
    }, 1e3);
  }
  /**
   * Preload content
   *
   * @param {boolean} isLazy
   * @param {boolean} [reload]
   */
  load(t, i) {
    if (this.slide && this.usePlaceholder())
      if (this.placeholder) {
        const e = this.placeholder.element;
        e && !e.parentElement && this.slide.container.prepend(e);
      } else {
        const e = this.instance.applyFilters(
          "placeholderSrc",
          // use  image-based placeholder only for the first slide,
          // as rendering (even small stretched thumbnail) is an expensive operation
          this.data.msrc && this.slide.isFirstSlide ? this.data.msrc : !1,
          this
        );
        this.placeholder = new Rt(e, this.slide.container);
      }
    this.element && !i || this.instance.dispatch("contentLoad", {
      content: this,
      isLazy: t
    }).defaultPrevented || (this.isImageContent() ? (this.element = f("pswp__img", "img"), this.displayedImageWidth && this.loadImage(t)) : (this.element = f("pswp__content", "div"), this.element.innerHTML = this.data.html || ""), i && this.slide && this.slide.updateContentSize(!0));
  }
  /**
   * Preload image
   *
   * @param {boolean} isLazy
   */
  loadImage(t) {
    var i, e;
    if (!this.isImageContent() || !this.element || this.instance.dispatch("contentLoadImage", {
      content: this,
      isLazy: t
    }).defaultPrevented)
      return;
    const s = (
      /** @type HTMLImageElement */
      this.element
    );
    this.updateSrcsetSizes(), this.data.srcset && (s.srcset = this.data.srcset), s.src = (i = this.data.src) !== null && i !== void 0 ? i : "", s.alt = (e = this.data.alt) !== null && e !== void 0 ? e : "", this.state = _.LOADING, s.complete ? this.onLoaded() : (s.onload = () => {
      this.onLoaded();
    }, s.onerror = () => {
      this.onError();
    });
  }
  /**
   * Assign slide to content
   *
   * @param {Slide} slide
   */
  setSlide(t) {
    this.slide = t, this.hasSlide = !0, this.instance = t.pswp;
  }
  /**
   * Content load success handler
   */
  onLoaded() {
    this.state = _.LOADED, this.slide && this.element && (this.instance.dispatch("loadComplete", {
      slide: this.slide,
      content: this
    }), this.slide.isActive && this.slide.heavyAppended && !this.element.parentNode && (this.append(), this.slide.updateContentSize(!0)), (this.state === _.LOADED || this.state === _.ERROR) && this.removePlaceholder());
  }
  /**
   * Content load error handler
   */
  onError() {
    this.state = _.ERROR, this.slide && (this.displayError(), this.instance.dispatch("loadComplete", {
      slide: this.slide,
      isError: !0,
      content: this
    }), this.instance.dispatch("loadError", {
      slide: this.slide,
      content: this
    }));
  }
  /**
   * @returns {Boolean} If the content is currently loading
   */
  isLoading() {
    return this.instance.applyFilters("isContentLoading", this.state === _.LOADING, this);
  }
  /**
   * @returns {Boolean} If the content is in error state
   */
  isError() {
    return this.state === _.ERROR;
  }
  /**
   * @returns {boolean} If the content is image
   */
  isImageContent() {
    return this.type === "image";
  }
  /**
   * Update content size
   *
   * @param {Number} width
   * @param {Number} height
   */
  setDisplayedSize(t, i) {
    if (this.element && (this.placeholder && this.placeholder.setDisplayedSize(t, i), !this.instance.dispatch("contentResize", {
      content: this,
      width: t,
      height: i
    }).defaultPrevented && (L(this.element, t, i), this.isImageContent() && !this.isError()))) {
      const e = !this.displayedImageWidth && t;
      this.displayedImageWidth = t, this.displayedImageHeight = i, e ? this.loadImage(!1) : this.updateSrcsetSizes(), this.slide && this.instance.dispatch("imageSizeChange", {
        slide: this.slide,
        width: t,
        height: i,
        content: this
      });
    }
  }
  /**
   * @returns {boolean} If the content can be zoomed
   */
  isZoomable() {
    return this.instance.applyFilters("isContentZoomable", this.isImageContent() && this.state !== _.ERROR, this);
  }
  /**
   * Update image srcset sizes attribute based on width and height
   */
  updateSrcsetSizes() {
    if (!this.isImageContent() || !this.element || !this.data.srcset)
      return;
    const t = (
      /** @type HTMLImageElement */
      this.element
    ), i = this.instance.applyFilters("srcsetSizesWidth", this.displayedImageWidth, this);
    (!t.dataset.largestUsedSize || i > parseInt(t.dataset.largestUsedSize, 10)) && (t.sizes = i + "px", t.dataset.largestUsedSize = String(i));
  }
  /**
   * @returns {boolean} If content should use a placeholder (from msrc by default)
   */
  usePlaceholder() {
    return this.instance.applyFilters("useContentPlaceholder", this.isImageContent(), this);
  }
  /**
   * Preload content with lazy-loading param
   */
  lazyLoad() {
    this.instance.dispatch("contentLazyLoad", {
      content: this
    }).defaultPrevented || this.load(!0);
  }
  /**
   * @returns {boolean} If placeholder should be kept after content is loaded
   */
  keepPlaceholder() {
    return this.instance.applyFilters("isKeepingPlaceholder", this.isLoading(), this);
  }
  /**
   * Destroy the content
   */
  destroy() {
    this.hasSlide = !1, this.slide = void 0, !this.instance.dispatch("contentDestroy", {
      content: this
    }).defaultPrevented && (this.remove(), this.placeholder && (this.placeholder.destroy(), this.placeholder = void 0), this.isImageContent() && this.element && (this.element.onload = null, this.element.onerror = null, this.element = void 0));
  }
  /**
   * Display error message
   */
  displayError() {
    if (this.slide) {
      var t, i;
      let e = f("pswp__error-msg", "div");
      e.innerText = (t = (i = this.instance.options) === null || i === void 0 ? void 0 : i.errorMsg) !== null && t !== void 0 ? t : "", e = /** @type {HTMLDivElement} */
      this.instance.applyFilters("contentErrorElement", e, this), this.element = f("pswp__content pswp__error-msg-container", "div"), this.element.appendChild(e), this.slide.container.innerText = "", this.slide.container.appendChild(this.element), this.slide.updateContentSize(!0), this.removePlaceholder();
    }
  }
  /**
   * Append the content
   */
  append() {
    if (this.isAttached || !this.element)
      return;
    if (this.isAttached = !0, this.state === _.ERROR) {
      this.displayError();
      return;
    }
    if (this.instance.dispatch("contentAppend", {
      content: this
    }).defaultPrevented)
      return;
    const t = "decode" in this.element;
    this.isImageContent() ? t && this.slide && (!this.slide.isActive || C()) ? (this.isDecoding = !0, this.element.decode().catch(() => {
    }).finally(() => {
      this.isDecoding = !1, this.appendImage();
    })) : this.appendImage() : this.slide && !this.element.parentNode && this.slide.container.appendChild(this.element);
  }
  /**
   * Activate the slide,
   * active slide is generally the current one,
   * meaning the user can see it.
   */
  activate() {
    this.instance.dispatch("contentActivate", {
      content: this
    }).defaultPrevented || !this.slide || (this.isImageContent() && this.isDecoding && !C() ? this.appendImage() : this.isError() && this.load(!1, !0), this.slide.holderElement && this.slide.holderElement.setAttribute("aria-hidden", "false"));
  }
  /**
   * Deactivate the content
   */
  deactivate() {
    this.instance.dispatch("contentDeactivate", {
      content: this
    }), this.slide && this.slide.holderElement && this.slide.holderElement.setAttribute("aria-hidden", "true");
  }
  /**
   * Remove the content from DOM
   */
  remove() {
    this.isAttached = !1, !this.instance.dispatch("contentRemove", {
      content: this
    }).defaultPrevented && (this.element && this.element.parentNode && this.element.remove(), this.placeholder && this.placeholder.element && this.placeholder.element.remove());
  }
  /**
   * Append the image content to slide container
   */
  appendImage() {
    this.isAttached && (this.instance.dispatch("contentAppendImage", {
      content: this
    }).defaultPrevented || (this.slide && this.element && !this.element.parentNode && this.slide.container.appendChild(this.element), (this.state === _.LOADED || this.state === _.ERROR) && this.removePlaceholder()));
  }
}
const Bt = 5;
function k(r, t, i) {
  const e = t.createContentFromData(r, i);
  let s;
  const {
    options: n
  } = t;
  if (n) {
    s = new B(n, r, -1);
    let o;
    t.pswp ? o = t.pswp.viewportSize : o = R(n, t);
    const a = F(n, o, r, i);
    s.update(e.width, e.height, a);
  }
  return e.lazyLoad(), s && e.setDisplayedSize(Math.ceil(e.width * s.initial), Math.ceil(e.height * s.initial)), e;
}
function Nt(r, t) {
  const i = t.getItemData(r);
  if (!t.dispatch("lazyLoadSlide", {
    index: r,
    itemData: i
  }).defaultPrevented)
    return k(i, t, r);
}
class kt {
  /**
   * @param {PhotoSwipe} pswp
   */
  constructor(t) {
    this.pswp = t, this.limit = Math.max(t.options.preload[0] + t.options.preload[1] + 1, Bt), this._cachedItems = [];
  }
  /**
   * Lazy load nearby slides based on `preload` option.
   *
   * @param {number} [diff] Difference between slide indexes that was changed recently, or 0.
   */
  updateLazy(t) {
    const {
      pswp: i
    } = this;
    if (i.dispatch("lazyLoad").defaultPrevented)
      return;
    const {
      preload: e
    } = i.options, s = t === void 0 ? !0 : t >= 0;
    let n;
    for (n = 0; n <= e[1]; n++)
      this.loadSlideByIndex(i.currIndex + (s ? n : -n));
    for (n = 1; n <= e[0]; n++)
      this.loadSlideByIndex(i.currIndex + (s ? -n : n));
  }
  /**
   * @param {number} initialIndex
   */
  loadSlideByIndex(t) {
    const i = this.pswp.getLoopedIndex(t);
    let e = this.getContentByIndex(i);
    e || (e = Nt(i, this.pswp), e && this.addToCache(e));
  }
  /**
   * @param {Slide} slide
   * @returns {Content}
   */
  getContentBySlide(t) {
    let i = this.getContentByIndex(t.index);
    return i || (i = this.pswp.createContentFromData(t.data, t.index), this.addToCache(i)), i.setSlide(t), i;
  }
  /**
   * @param {Content} content
   */
  addToCache(t) {
    if (this.removeByIndex(t.index), this._cachedItems.push(t), this._cachedItems.length > this.limit) {
      const i = this._cachedItems.findIndex((e) => !e.isAttached && !e.hasSlide);
      i !== -1 && this._cachedItems.splice(i, 1)[0].destroy();
    }
  }
  /**
   * Removes an image from cache, does not destroy() it, just removes.
   *
   * @param {number} index
   */
  removeByIndex(t) {
    const i = this._cachedItems.findIndex((e) => e.index === t);
    i !== -1 && this._cachedItems.splice(i, 1);
  }
  /**
   * @param {number} index
   * @returns {Content | undefined}
   */
  getContentByIndex(t) {
    return this._cachedItems.find((i) => i.index === t);
  }
  destroy() {
    this._cachedItems.forEach((t) => t.destroy()), this._cachedItems = [];
  }
}
class Ht extends Mt {
  /**
   * Get total number of slides
   *
   * @returns {number}
   */
  getNumItems() {
    var t;
    let i = 0;
    const e = (t = this.options) === null || t === void 0 ? void 0 : t.dataSource;
    e && "length" in e ? i = e.length : e && "gallery" in e && (e.items || (e.items = this._getGalleryDOMElements(e.gallery)), e.items && (i = e.items.length));
    const s = this.dispatch("numItems", {
      dataSource: e,
      numItems: i
    });
    return this.applyFilters("numItems", s.numItems, e);
  }
  /**
   * @param {SlideData} slideData
   * @param {number} index
   * @returns {Content}
   */
  createContentFromData(t, i) {
    return new Ft(t, this, i);
  }
  /**
   * Get item data by index.
   *
   * "item data" should contain normalized information that PhotoSwipe needs to generate a slide.
   * For example, it may contain properties like
   * `src`, `srcset`, `w`, `h`, which will be used to generate a slide with image.
   *
   * @param {number} index
   * @returns {SlideData}
   */
  getItemData(t) {
    var i;
    const e = (i = this.options) === null || i === void 0 ? void 0 : i.dataSource;
    let s = {};
    Array.isArray(e) ? s = e[t] : e && "gallery" in e && (e.items || (e.items = this._getGalleryDOMElements(e.gallery)), s = e.items[t]);
    let n = s;
    n instanceof Element && (n = this._domElementToItemData(n));
    const o = this.dispatch("itemData", {
      itemData: n || {},
      index: t
    });
    return this.applyFilters("itemData", o.itemData, t);
  }
  /**
   * Get array of gallery DOM elements,
   * based on childSelector and gallery element.
   *
   * @param {HTMLElement} galleryElement
   * @returns {HTMLElement[]}
   */
  _getGalleryDOMElements(t) {
    var i, e;
    return (i = this.options) !== null && i !== void 0 && i.children || (e = this.options) !== null && e !== void 0 && e.childSelector ? q(this.options.children, this.options.childSelector, t) || [] : [t];
  }
  /**
   * Converts DOM element to item data object.
   *
   * @param {HTMLElement} element DOM element
   * @returns {SlideData}
   */
  _domElementToItemData(t) {
    const i = {
      element: t
    }, e = (
      /** @type {HTMLAnchorElement} */
      t.tagName === "A" ? t : t.querySelector("a")
    );
    if (e) {
      i.src = e.dataset.pswpSrc || e.href, e.dataset.pswpSrcset && (i.srcset = e.dataset.pswpSrcset), i.width = e.dataset.pswpWidth ? parseInt(e.dataset.pswpWidth, 10) : 0, i.height = e.dataset.pswpHeight ? parseInt(e.dataset.pswpHeight, 10) : 0, i.w = i.width, i.h = i.height, e.dataset.pswpType && (i.type = e.dataset.pswpType);
      const n = t.querySelector("img");
      if (n) {
        var s;
        i.msrc = n.currentSrc || n.src, i.alt = (s = n.getAttribute("alt")) !== null && s !== void 0 ? s : "";
      }
      (e.dataset.pswpCropped || e.dataset.cropped) && (i.thumbCropped = !0);
    }
    return this.applyFilters("domItemData", i, t, e);
  }
  /**
   * Lazy-load by slide data
   *
   * @param {SlideData} itemData Data about the slide
   * @param {number} index
   * @returns {Content} Image that is being decoded or false.
   */
  lazyLoadData(t, i) {
    return k(t, this, i);
  }
}
const P = 3e-3;
class Wt {
  /**
   * @param {PhotoSwipe} pswp
   */
  constructor(t) {
    this.pswp = t, this.isClosed = !0, this.isOpen = !1, this.isClosing = !1, this.isOpening = !1, this._duration = void 0, this._useAnimation = !1, this._croppedZoom = !1, this._animateRootOpacity = !1, this._animateBgOpacity = !1, this._placeholder = void 0, this._opacityElement = void 0, this._cropContainer1 = void 0, this._cropContainer2 = void 0, this._thumbBounds = void 0, this._prepareOpen = this._prepareOpen.bind(this), t.on("firstZoomPan", this._prepareOpen);
  }
  open() {
    this._prepareOpen(), this._start();
  }
  close() {
    if (this.isClosed || this.isClosing || this.isOpening)
      return;
    const t = this.pswp.currSlide;
    this.isOpen = !1, this.isOpening = !1, this.isClosing = !0, this._duration = this.pswp.options.hideAnimationDuration, t && t.currZoomLevel * t.width >= this.pswp.options.maxWidthToAnimate && (this._duration = 0), this._applyStartProps(), setTimeout(() => {
      this._start();
    }, this._croppedZoom ? 30 : 0);
  }
  /** @private */
  _prepareOpen() {
    if (this.pswp.off("firstZoomPan", this._prepareOpen), !this.isOpening) {
      const t = this.pswp.currSlide;
      this.isOpening = !0, this.isClosing = !1, this._duration = this.pswp.options.showAnimationDuration, t && t.zoomLevels.initial * t.width >= this.pswp.options.maxWidthToAnimate && (this._duration = 0), this._applyStartProps();
    }
  }
  /** @private */
  _applyStartProps() {
    const {
      pswp: t
    } = this, i = this.pswp.currSlide, {
      options: e
    } = t;
    if (e.showHideAnimationType === "fade" ? (e.showHideOpacity = !0, this._thumbBounds = void 0) : e.showHideAnimationType === "none" ? (e.showHideOpacity = !1, this._duration = 0, this._thumbBounds = void 0) : this.isOpening && t._initialThumbBounds ? this._thumbBounds = t._initialThumbBounds : this._thumbBounds = this.pswp.getThumbBounds(), this._placeholder = i == null ? void 0 : i.getPlaceholderElement(), t.animations.stopAll(), this._useAnimation = !!(this._duration && this._duration > 50), this._animateZoom = !!this._thumbBounds && (i == null ? void 0 : i.content.usePlaceholder()) && (!this.isClosing || !t.mainScroll.isShifted()), !this._animateZoom)
      this._animateRootOpacity = !0, this.isOpening && i && (i.zoomAndPanToInitial(), i.applyCurrentZoomPan());
    else {
      var s;
      this._animateRootOpacity = (s = e.showHideOpacity) !== null && s !== void 0 ? s : !1;
    }
    if (this._animateBgOpacity = !this._animateRootOpacity && this.pswp.options.bgOpacity > P, this._opacityElement = this._animateRootOpacity ? t.element : t.bg, !this._useAnimation) {
      this._duration = 0, this._animateZoom = !1, this._animateBgOpacity = !1, this._animateRootOpacity = !0, this.isOpening && (t.element && (t.element.style.opacity = String(P)), t.applyBgOpacity(1));
      return;
    }
    if (this._animateZoom && this._thumbBounds && this._thumbBounds.innerRect) {
      var n;
      this._croppedZoom = !0, this._cropContainer1 = this.pswp.container, this._cropContainer2 = (n = this.pswp.currSlide) === null || n === void 0 ? void 0 : n.holderElement, t.container && (t.container.style.overflow = "hidden", t.container.style.width = t.viewportSize.x + "px");
    } else
      this._croppedZoom = !1;
    this.isOpening ? (this._animateRootOpacity ? (t.element && (t.element.style.opacity = String(P)), t.applyBgOpacity(1)) : (this._animateBgOpacity && t.bg && (t.bg.style.opacity = String(P)), t.element && (t.element.style.opacity = "1")), this._animateZoom && (this._setClosedStateZoomPan(), this._placeholder && (this._placeholder.style.willChange = "transform", this._placeholder.style.opacity = String(P)))) : this.isClosing && (t.mainScroll.itemHolders[0] && (t.mainScroll.itemHolders[0].el.style.display = "none"), t.mainScroll.itemHolders[2] && (t.mainScroll.itemHolders[2].el.style.display = "none"), this._croppedZoom && t.mainScroll.x !== 0 && (t.mainScroll.resetPosition(), t.mainScroll.resize()));
  }
  /** @private */
  _start() {
    this.isOpening && this._useAnimation && this._placeholder && this._placeholder.tagName === "IMG" ? new Promise((t) => {
      let i = !1, e = !0;
      $(
        /** @type {HTMLImageElement} */
        this._placeholder
      ).finally(() => {
        i = !0, e || t(!0);
      }), setTimeout(() => {
        e = !1, i && t(!0);
      }, 50), setTimeout(t, 250);
    }).finally(() => this._initiate()) : this._initiate();
  }
  /** @private */
  _initiate() {
    var t, i;
    (t = this.pswp.element) === null || t === void 0 || t.style.setProperty("--pswp-transition-duration", this._duration + "ms"), this.pswp.dispatch(this.isOpening ? "openingAnimationStart" : "closingAnimationStart"), this.pswp.dispatch(
      /** @type {'initialZoomIn' | 'initialZoomOut'} */
      "initialZoom" + (this.isOpening ? "In" : "Out")
    ), (i = this.pswp.element) === null || i === void 0 || i.classList.toggle("pswp--ui-visible", this.isOpening), this.isOpening ? (this._placeholder && (this._placeholder.style.opacity = "1"), this._animateToOpenState()) : this.isClosing && this._animateToClosedState(), this._useAnimation || this._onAnimationComplete();
  }
  /** @private */
  _onAnimationComplete() {
    const {
      pswp: t
    } = this;
    if (this.isOpen = this.isOpening, this.isClosed = this.isClosing, this.isOpening = !1, this.isClosing = !1, t.dispatch(this.isOpen ? "openingAnimationEnd" : "closingAnimationEnd"), t.dispatch(
      /** @type {'initialZoomInEnd' | 'initialZoomOutEnd'} */
      "initialZoom" + (this.isOpen ? "InEnd" : "OutEnd")
    ), this.isClosed)
      t.destroy();
    else if (this.isOpen) {
      var i;
      this._animateZoom && t.container && (t.container.style.overflow = "visible", t.container.style.width = "100%"), (i = t.currSlide) === null || i === void 0 || i.applyCurrentZoomPan();
    }
  }
  /** @private */
  _animateToOpenState() {
    const {
      pswp: t
    } = this;
    this._animateZoom && (this._croppedZoom && this._cropContainer1 && this._cropContainer2 && (this._animateTo(this._cropContainer1, "transform", "translate3d(0,0,0)"), this._animateTo(this._cropContainer2, "transform", "none")), t.currSlide && (t.currSlide.zoomAndPanToInitial(), this._animateTo(t.currSlide.container, "transform", t.currSlide.getCurrentTransform()))), this._animateBgOpacity && t.bg && this._animateTo(t.bg, "opacity", String(t.options.bgOpacity)), this._animateRootOpacity && t.element && this._animateTo(t.element, "opacity", "1");
  }
  /** @private */
  _animateToClosedState() {
    const {
      pswp: t
    } = this;
    this._animateZoom && this._setClosedStateZoomPan(!0), this._animateBgOpacity && t.bgOpacity > 0.01 && t.bg && this._animateTo(t.bg, "opacity", "0"), this._animateRootOpacity && t.element && this._animateTo(t.element, "opacity", "0");
  }
  /**
   * @private
   * @param {boolean} [animate]
   */
  _setClosedStateZoomPan(t) {
    if (!this._thumbBounds) return;
    const {
      pswp: i
    } = this, {
      innerRect: e
    } = this._thumbBounds, {
      currSlide: s,
      viewportSize: n
    } = i;
    if (this._croppedZoom && e && this._cropContainer1 && this._cropContainer2) {
      const o = -n.x + (this._thumbBounds.x - e.x) + e.w, a = -n.y + (this._thumbBounds.y - e.y) + e.h, h = n.x - e.w, l = n.y - e.h;
      t ? (this._animateTo(this._cropContainer1, "transform", I(o, a)), this._animateTo(this._cropContainer2, "transform", I(h, l))) : (y(this._cropContainer1, o, a), y(this._cropContainer2, h, l));
    }
    s && (p(s.pan, e || this._thumbBounds), s.currZoomLevel = this._thumbBounds.w / s.width, t ? this._animateTo(s.container, "transform", s.getCurrentTransform()) : s.applyCurrentZoomPan());
  }
  /**
   * @private
   * @param {HTMLElement} target
   * @param {'transform' | 'opacity'} prop
   * @param {string} propValue
   */
  _animateTo(t, i, e) {
    if (!this._duration) {
      t.style[i] = e;
      return;
    }
    const {
      animations: s
    } = this.pswp, n = {
      duration: this._duration,
      easing: this.pswp.options.easing,
      onComplete: () => {
        s.activeAnimations.length || this._onAnimationComplete();
      },
      target: t
    };
    n[i] = e, s.startTransition(n);
  }
}
const Vt = {
  allowPanToNext: !0,
  spacing: 0.1,
  loop: !0,
  pinchToClose: !0,
  closeOnVerticalDrag: !0,
  hideAnimationDuration: 333,
  showAnimationDuration: 333,
  zoomAnimationDuration: 333,
  escKey: !0,
  arrowKeys: !0,
  trapFocus: !0,
  returnFocus: !0,
  maxWidthToAnimate: 4e3,
  clickToCloseNonZoomable: !0,
  imageClickAction: "zoom-or-close",
  bgClickAction: "close",
  tapAction: "toggle-controls",
  doubleTapAction: "zoom",
  indexIndicatorSep: " / ",
  preloaderDelay: 2e3,
  bgOpacity: 0.8,
  index: 0,
  errorMsg: "The image cannot be loaded",
  preload: [1, 2],
  easing: "cubic-bezier(.4,0,.22,1)"
};
class $t extends Ht {
  /**
   * @param {PhotoSwipeOptions} [options]
   */
  constructor(t) {
    super(), this.options = this._prepareOptions(t || {}), this.offset = {
      x: 0,
      y: 0
    }, this._prevViewportSize = {
      x: 0,
      y: 0
    }, this.viewportSize = {
      x: 0,
      y: 0
    }, this.bgOpacity = 1, this.currIndex = 0, this.potentialIndex = 0, this.isOpen = !1, this.isDestroying = !1, this.hasMouse = !1, this._initialItemData = {}, this._initialThumbBounds = void 0, this.topBar = void 0, this.element = void 0, this.template = void 0, this.container = void 0, this.scrollWrap = void 0, this.currSlide = void 0, this.events = new G(), this.animations = new wt(), this.mainScroll = new dt(this), this.gestures = new lt(this), this.opener = new Wt(this), this.keyboard = new ut(this), this.contentLoader = new kt(this);
  }
  /** @returns {boolean} */
  init() {
    if (this.isOpen || this.isDestroying)
      return !1;
    this.isOpen = !0, this.dispatch("init"), this.dispatch("beforeOpen"), this._createMainStructure();
    let t = "pswp--open";
    return this.gestures.supportsTouch && (t += " pswp--touch"), this.options.mainClass && (t += " " + this.options.mainClass), this.element && (this.element.className += " " + t), this.currIndex = this.options.index || 0, this.potentialIndex = this.currIndex, this.dispatch("firstUpdate"), this.scrollWheel = new Pt(this), (Number.isNaN(this.currIndex) || this.currIndex < 0 || this.currIndex >= this.getNumItems()) && (this.currIndex = 0), this.gestures.supportsTouch || this.mouseDetected(), this.updateSize(), this.offset.y = window.pageYOffset, this._initialItemData = this.getItemData(this.currIndex), this.dispatch("gettingData", {
      index: this.currIndex,
      data: this._initialItemData,
      slide: void 0
    }), this._initialThumbBounds = this.getThumbBounds(), this.dispatch("initialLayout"), this.on("openingAnimationEnd", () => {
      const {
        itemHolders: i
      } = this.mainScroll;
      i[0] && (i[0].el.style.display = "block", this.setContent(i[0], this.currIndex - 1)), i[2] && (i[2].el.style.display = "block", this.setContent(i[2], this.currIndex + 1)), this.appendHeavy(), this.contentLoader.updateLazy(), this.events.add(window, "resize", this._handlePageResize.bind(this)), this.events.add(window, "scroll", this._updatePageScrollOffset.bind(this)), this.dispatch("bindEvents");
    }), this.mainScroll.itemHolders[1] && this.setContent(this.mainScroll.itemHolders[1], this.currIndex), this.dispatch("change"), this.opener.open(), this.dispatch("afterInit"), !0;
  }
  /**
   * Get looped slide index
   * (for example, -1 will return the last slide)
   *
   * @param {number} index
   * @returns {number}
   */
  getLoopedIndex(t) {
    const i = this.getNumItems();
    return this.options.loop && (t > i - 1 && (t -= i), t < 0 && (t += i)), b(t, 0, i - 1);
  }
  appendHeavy() {
    this.mainScroll.itemHolders.forEach((t) => {
      var i;
      (i = t.slide) === null || i === void 0 || i.appendHeavy();
    });
  }
  /**
   * Change the slide
   * @param {number} index New index
   */
  goTo(t) {
    this.mainScroll.moveIndexBy(this.getLoopedIndex(t) - this.potentialIndex);
  }
  /**
   * Go to the next slide.
   */
  next() {
    this.goTo(this.potentialIndex + 1);
  }
  /**
   * Go to the previous slide.
   */
  prev() {
    this.goTo(this.potentialIndex - 1);
  }
  /**
   * @see slide/slide.js zoomTo
   *
   * @param {Parameters<Slide['zoomTo']>} args
   */
  zoomTo(...t) {
    var i;
    (i = this.currSlide) === null || i === void 0 || i.zoomTo(...t);
  }
  /**
   * @see slide/slide.js toggleZoom
   */
  toggleZoom() {
    var t;
    (t = this.currSlide) === null || t === void 0 || t.toggleZoom();
  }
  /**
   * Close the gallery.
   * After closing transition ends - destroy it
   */
  close() {
    !this.opener.isOpen || this.isDestroying || (this.isDestroying = !0, this.dispatch("close"), this.events.removeAll(), this.opener.close());
  }
  /**
   * Destroys the gallery:
   * - instantly closes the gallery
   * - unbinds events,
   * - cleans intervals and timeouts
   * - removes elements from DOM
   */
  destroy() {
    var t;
    if (!this.isDestroying) {
      this.options.showHideAnimationType = "none", this.close();
      return;
    }
    this.dispatch("destroy"), this._listeners = {}, this.scrollWrap && (this.scrollWrap.ontouchmove = null, this.scrollWrap.ontouchend = null), (t = this.element) === null || t === void 0 || t.remove(), this.mainScroll.itemHolders.forEach((i) => {
      var e;
      (e = i.slide) === null || e === void 0 || e.destroy();
    }), this.contentLoader.destroy(), this.events.removeAll();
  }
  /**
   * Refresh/reload content of a slide by its index
   *
   * @param {number} slideIndex
   */
  refreshSlideContent(t) {
    this.contentLoader.removeByIndex(t), this.mainScroll.itemHolders.forEach((i, e) => {
      var s, n;
      let o = ((s = (n = this.currSlide) === null || n === void 0 ? void 0 : n.index) !== null && s !== void 0 ? s : 0) - 1 + e;
      if (this.canLoop() && (o = this.getLoopedIndex(o)), o === t && (this.setContent(i, t, !0), e === 1)) {
        var a;
        this.currSlide = i.slide, (a = i.slide) === null || a === void 0 || a.setIsActive(!0);
      }
    }), this.dispatch("change");
  }
  /**
   * Set slide content
   *
   * @param {ItemHolder} holder mainScroll.itemHolders array item
   * @param {number} index Slide index
   * @param {boolean} [force] If content should be set even if index wasn't changed
   */
  setContent(t, i, e) {
    if (this.canLoop() && (i = this.getLoopedIndex(i)), t.slide) {
      if (t.slide.index === i && !e)
        return;
      t.slide.destroy(), t.slide = void 0;
    }
    if (!this.canLoop() && (i < 0 || i >= this.getNumItems()))
      return;
    const s = this.getItemData(i);
    t.slide = new X(s, i, this), i === this.currIndex && (this.currSlide = t.slide), t.slide.append(t.el);
  }
  /** @returns {Point} */
  getViewportCenterPoint() {
    return {
      x: this.viewportSize.x / 2,
      y: this.viewportSize.y / 2
    };
  }
  /**
   * Update size of all elements.
   * Executed on init and on page resize.
   *
   * @param {boolean} [force] Update size even if size of viewport was not changed.
   */
  updateSize(t) {
    if (this.isDestroying)
      return;
    const i = R(this.options, this);
    !t && x(i, this._prevViewportSize) || (p(this._prevViewportSize, i), this.dispatch("beforeResize"), p(this.viewportSize, this._prevViewportSize), this._updatePageScrollOffset(), this.dispatch("viewportSize"), this.mainScroll.resize(this.opener.isOpen), !this.hasMouse && window.matchMedia("(any-hover: hover)").matches && this.mouseDetected(), this.dispatch("resize"));
  }
  /**
   * @param {number} opacity
   */
  applyBgOpacity(t) {
    this.bgOpacity = Math.max(t, 0), this.bg && (this.bg.style.opacity = String(this.bgOpacity * this.options.bgOpacity));
  }
  /**
   * Whether mouse is detected
   */
  mouseDetected() {
    if (!this.hasMouse) {
      var t;
      this.hasMouse = !0, (t = this.element) === null || t === void 0 || t.classList.add("pswp--has_mouse");
    }
  }
  /**
   * Page resize event handler
   *
   * @private
   */
  _handlePageResize() {
    this.updateSize(), /iPhone|iPad|iPod/i.test(window.navigator.userAgent) && setTimeout(() => {
      this.updateSize();
    }, 500);
  }
  /**
   * Page scroll offset is used
   * to get correct coordinates
   * relative to PhotoSwipe viewport.
   *
   * @private
   */
  _updatePageScrollOffset() {
    this.setScrollOffset(0, window.pageYOffset);
  }
  /**
   * @param {number} x
   * @param {number} y
   */
  setScrollOffset(t, i) {
    this.offset.x = t, this.offset.y = i, this.dispatch("updateScrollOffset");
  }
  /**
   * Create main HTML structure of PhotoSwipe,
   * and add it to DOM
   *
   * @private
   */
  _createMainStructure() {
    this.element = f("pswp", "div"), this.element.setAttribute("tabindex", "-1"), this.element.setAttribute("role", "dialog"), this.template = this.element, this.bg = f("pswp__bg", "div", this.element), this.scrollWrap = f("pswp__scroll-wrap", "section", this.element), this.container = f("pswp__container", "div", this.scrollWrap), this.scrollWrap.setAttribute("aria-roledescription", "carousel"), this.container.setAttribute("aria-live", "off"), this.container.setAttribute("id", "pswp__items"), this.mainScroll.appendHolders(), this.ui = new zt(this), this.ui.init(), (this.options.appendToEl || document.body).appendChild(this.element);
  }
  /**
   * Get position and dimensions of small thumbnail
   *   {x:,y:,w:}
   *
   * Height is optional (calculated based on the large image)
   *
   * @returns {Bounds | undefined}
   */
  getThumbBounds() {
    return Zt(this.currIndex, this.currSlide ? this.currSlide.data : this._initialItemData, this);
  }
  /**
   * If the PhotoSwipe can have continuous loop
   * @returns Boolean
   */
  canLoop() {
    return this.options.loop && this.getNumItems() > 2;
  }
  /**
   * @private
   * @param {PhotoSwipeOptions} options
   * @returns {PreparedPhotoSwipeOptions}
   */
  _prepareOptions(t) {
    return window.matchMedia("(prefers-reduced-motion), (update: slow)").matches && (t.showHideAnimationType = "none", t.zoomAnimationDuration = 0), {
      ...Vt,
      ...t
    };
  }
}
export {
  $t as default
};