import React, { useRef, useState, useEffect, Component } from 'react';
import PropTypes from 'prop-types';
import Modal from 'react-modal';
import { UncontrolledTooltip } from 'reactstrap';
import classnames from 'classnames';

function _arrayLikeToArray(r, a) {
  (null == a || a > r.length) && (a = r.length);
  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
  return n;
}
function _arrayWithHoles(r) {
  if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles(r) {
  if (Array.isArray(r)) return _arrayLikeToArray(r);
}
function _assertThisInitialized(e) {
  if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  return e;
}
function _callSuper(t, o, e) {
  return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _classCallCheck(a, n) {
  if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _defineProperties(e, r) {
  for (var t = 0; t < r.length; t++) {
    var o = r[t];
    o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
  }
}
function _createClass(e, r, t) {
  return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
    writable: !1
  }), e;
}
function _defineProperty(e, r, t) {
  return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
    value: t,
    enumerable: !0,
    configurable: !0,
    writable: !0
  }) : e[r] = t, e;
}
function _extends() {
  return _extends = Object.assign ? Object.assign.bind() : function (n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends.apply(null, arguments);
}
function _getPrototypeOf(t) {
  return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
    return t.__proto__ || Object.getPrototypeOf(t);
  }, _getPrototypeOf(t);
}
function _inherits(t, e) {
  if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
  t.prototype = Object.create(e && e.prototype, {
    constructor: {
      value: t,
      writable: !0,
      configurable: !0
    }
  }), Object.defineProperty(t, "prototype", {
    writable: !1
  }), e && _setPrototypeOf(t, e);
}
function _isNativeReflectConstruct() {
  try {
    var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
  } catch (t) {}
  return (_isNativeReflectConstruct = function () {
    return !!t;
  })();
}
function _iterableToArray(r) {
  if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit(r, l) {
  var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
  if (null != t) {
    var e,
      n,
      i,
      u,
      a = [],
      f = !0,
      o = !1;
    try {
      if (i = (t = t.call(r)).next, 0 === l) {
        if (Object(t) !== t) return;
        f = !1;
      } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
    } catch (r) {
      o = !0, n = r;
    } finally {
      try {
        if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
      } finally {
        if (o) throw n;
      }
    }
    return a;
  }
}
function _nonIterableRest() {
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableSpread() {
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function ownKeys(e, r) {
  var t = Object.keys(e);
  if (Object.getOwnPropertySymbols) {
    var o = Object.getOwnPropertySymbols(e);
    r && (o = o.filter(function (r) {
      return Object.getOwnPropertyDescriptor(e, r).enumerable;
    })), t.push.apply(t, o);
  }
  return t;
}
function _objectSpread2(e) {
  for (var r = 1; r < arguments.length; r++) {
    var t = null != arguments[r] ? arguments[r] : {};
    r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
      _defineProperty(e, r, t[r]);
    }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
      Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
    });
  }
  return e;
}
function _possibleConstructorReturn(t, e) {
  if (e && ("object" == typeof e || "function" == typeof e)) return e;
  if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
  return _assertThisInitialized(t);
}
function _setPrototypeOf(t, e) {
  return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
    return t.__proto__ = e, t;
  }, _setPrototypeOf(t, e);
}
function _slicedToArray(r, e) {
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toConsumableArray(r) {
  return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _toPrimitive(t, r) {
  if ("object" != typeof t || !t) return t;
  var e = t[Symbol.toPrimitive];
  if (void 0 !== e) {
    var i = e.call(t, r || "default");
    if ("object" != typeof i) return i;
    throw new TypeError("@@toPrimitive must return a primitive value.");
  }
  return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
  var i = _toPrimitive(t, "string");
  return "symbol" == typeof i ? i : i + "";
}
function _unsupportedIterableToArray(r, a) {
  if (r) {
    if ("string" == typeof r) return _arrayLikeToArray(r, a);
    var t = {}.toString.call(r).slice(8, -1);
    return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
  }
}

/**
 * Placeholder for future translate functionality
 */
function translate(str) {
  var replaceStrings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  if (!str) {
    return '';
  }
  var translated = str;
  if (replaceStrings) {
    Object.keys(replaceStrings).forEach(function (placeholder) {
      translated = translated.replace(placeholder, replaceStrings[placeholder]);
    });
  }
  return translated;
}
function getWindowWidth() {
  return typeof global.window !== 'undefined' ? global.window.innerWidth : 0;
}
function getWindowHeight() {
  return typeof global.window !== 'undefined' ? global.window.innerHeight : 0;
}
var isMobile = typeof window !== 'undefined' && (window.innerWidth < 768 || navigator.userAgent.toLowerCase().match(/(ipod|ipad|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i) != null);

// Get the highest window context that isn't cross-origin
// (When in an iframe)
function getHighestSafeWindowContext() {
  var self = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : global.window.self;
  var referrer = self.document.referrer;
  // If we reached the top level, return self
  if (self === global.window.top || !referrer) {
    return self;
  }
  var getOrigin = function getOrigin(href) {
    return href.match(/(.*\/\/.*?)(\/|$)/)[1];
  };

  // If parent is the same origin, we can move up one context
  // Reference: https://stackoverflow.com/a/21965342/1601953
  if (getOrigin(self.location.href) === getOrigin(referrer)) {
    return getHighestSafeWindowContext(self.parent);
  }

  // If a different origin, we consider the current level
  // as the top reachable one
  return self;
}

// Min image zoom level
var MIN_ZOOM_LEVEL = 0;

// Max image zoom level
var MAX_ZOOM_LEVEL = 5;

// Size ratio between previous and next zoom levels
var ZOOM_RATIO = 1.2;

// How much to increase/decrease the zoom level when the zoom buttons are clicked
var ZOOM_BUTTON_INCREMENT_SIZE = 1;

// Used to judge the amount of vertical scroll needed to initiate a zoom action
var WHEEL_MOVE_Y_THRESHOLD = 1;
var KEYS = {
  ESC: 27,
  LEFT_ARROW: 37,
  UP_ARROW: 38,
  RIGHT_ARROW: 39,
  DOWN_ARROW: 40
};

// Actions
var ACTION_NONE = 0;
var ACTION_MOVE = 1;
var ACTION_SWIPE = 2;
var ACTION_PINCH = 3;

// Events source
var SOURCE_ANY = 0;
var SOURCE_MOUSE = 1;
var SOURCE_TOUCH = 2;
var SOURCE_POINTER = 3;

// Minimal swipe distance
var MIN_SWIPE_DISTANCE = 200;

var Tooltip = function Tooltip(_ref) {
  var target = _ref.target,
    children = _ref.children,
    className = _ref.className,
    _ref$modifiers = _ref.modifiers,
    modifiers = _ref$modifiers === void 0 ? [] : _ref$modifiers,
    _ref$placement = _ref.placement,
    placement = _ref$placement === void 0 ? 'right' : _ref$placement,
    _ref$fade = _ref.fade,
    fade = _ref$fade === void 0 ? false : _ref$fade,
    _ref$delay = _ref.delay,
    delay = _ref$delay === void 0 ? 0 : _ref$delay;
  var hasBoundary = modifiers.find(function (item) {
    return item.name === 'preventOverflow';
  });
  var newModifiers = hasBoundary ? modifiers : [].concat(_toConsumableArray(modifiers), [{
    name: 'preventOverflow',
    options: {
      boundary: window.document.body
    }
  }]);
  var props = {
    popperClassName: classnames('seafile-image-tooltip', className),
    modifiers: newModifiers,
    placement: placement,
    target: target,
    fade: fade,
    delay: delay
  };
  return /*#__PURE__*/React.createElement(UncontrolledTooltip, props, children);
};
Tooltip.propTypes = {
  target: PropTypes.string.isRequired,
  className: PropTypes.string,
  placement: PropTypes.string,
  children: PropTypes.any,
  fade: PropTypes.bool
};

var SidebarThumbnails = function SidebarThumbnails(props) {
  var images = props.imageItems,
    currentIndex = props.currentIndex,
    setImageIndex = props.setImageIndex;
  var listRef = useRef(null);
  var itemRefs = useRef([]);
  var _useState = useState(false),
    _useState2 = _slicedToArray(_useState, 2),
    isDidMount = _useState2[0],
    setDidMount = _useState2[1];
  useEffect(function () {
    setDidMount(true);
  }, []);
  useEffect(function () {
    var listEl = listRef.current;
    var itemEl = itemRefs.current[currentIndex];
    if (!listEl || !itemEl) return;
    var itemCenter = itemEl.offsetTop + itemEl.offsetHeight / 2;
    var targetScrollTop = itemCenter - listEl.clientHeight / 2;
    var maxScroll = listEl.scrollHeight - listEl.clientHeight;
    var nextScrollTop = Math.max(0, Math.min(targetScrollTop, maxScroll));
    listEl.scrollTo({
      top: nextScrollTop,
      behavior: 'smooth'
    });
  }, [currentIndex, images.length]);
  return /*#__PURE__*/React.createElement("div", {
    className: "thumbnail-sidebar",
    ref: listRef,
    onWheel: function onWheel(e) {
      e.stopPropagation();
    }
  }, images.map(function (img, i) {
    var thumbId = img.id ? "ril-thumb-".concat(img.id) : "ril-thumb-".concat(i);
    return /*#__PURE__*/React.createElement("div", {
      key: thumbId,
      id: thumbId,
      ref: function ref(el) {
        return itemRefs.current[i] = el;
      },
      className: "ril-thumb ".concat(i === currentIndex ? 'thumb-active' : ''),
      onClick: function onClick() {
        return setImageIndex && setImageIndex(i);
      }
    }, /*#__PURE__*/React.createElement("img", {
      src: img.thumbnail || img,
      alt: ""
    }), isDidMount && /*#__PURE__*/React.createElement(Tooltip, {
      target: thumbId
    }, img.name || img));
  }));
};

var ReactImageLightbox = /*#__PURE__*/function (_Component) {
  function ReactImageLightbox(props) {
    var _this;
    _classCallCheck(this, ReactImageLightbox);
    _this = _callSuper(this, ReactImageLightbox, [props]);
    _this.state = {
      //-----------------------------
      // Animation
      //-----------------------------

      // Lightbox is closing
      // When Lightbox is mounted, if animation is enabled it will open with the reverse of the closing animation
      isClosing: !props.animationDisabled,
      // Component parts should animate (e.g., when images are moving, or image is being zoomed)
      shouldAnimate: false,
      //-----------------------------
      // Zoom settings
      //-----------------------------
      // Zoom level of image
      zoomLevel: MIN_ZOOM_LEVEL,
      //-----------------------------
      // Image position settings
      //-----------------------------
      // Horizontal offset from center
      offsetX: 0,
      // Vertical offset from center
      offsetY: 0,
      // image load error for srcType
      loadErrorStatus: {},
      // rotate image degree
      rotateDeg: 0
    };

    // Refs
    _this.outerEl = /*#__PURE__*/React.createRef();
    _this.zoomInBtn = /*#__PURE__*/React.createRef();
    _this.zoomOutBtn = /*#__PURE__*/React.createRef();
    _this.caption = /*#__PURE__*/React.createRef();
    _this.closeIfClickInner = _this.closeIfClickInner.bind(_this);
    _this.handleImageDoubleClick = _this.handleImageDoubleClick.bind(_this);
    _this.handleImageClick = _this.handleImageClick.bind(_this);
    _this.handleImageMouseWheel = _this.handleImageMouseWheel.bind(_this);
    _this.handleKeyInput = _this.handleKeyInput.bind(_this);
    _this.handleMouseUp = _this.handleMouseUp.bind(_this);
    _this.handleMouseDown = _this.handleMouseDown.bind(_this);
    _this.handleMouseMove = _this.handleMouseMove.bind(_this);
    _this.handleOuterMousewheel = _this.handleOuterMousewheel.bind(_this);
    _this.handleTouchStart = _this.handleTouchStart.bind(_this);
    _this.handleTouchMove = _this.handleTouchMove.bind(_this);
    _this.handleTouchEnd = _this.handleTouchEnd.bind(_this);
    _this.handlePointerEvent = _this.handlePointerEvent.bind(_this);
    _this.handleCaptionMousewheel = _this.handleCaptionMousewheel.bind(_this);
    _this.handleWindowResize = _this.handleWindowResize.bind(_this);
    _this.handleZoomInButtonClick = _this.handleZoomInButtonClick.bind(_this);
    _this.handleZoomOutButtonClick = _this.handleZoomOutButtonClick.bind(_this);
    _this.requestClose = _this.requestClose.bind(_this);
    _this.requestMoveNext = _this.requestMoveNext.bind(_this);
    _this.requestMovePrev = _this.requestMovePrev.bind(_this);
    _this.requestMoveUp = _this.requestMoveUp.bind(_this);
    _this.requestMoveDown = _this.requestMoveDown.bind(_this);
    _this.rotateImage = _this.rotateImage.bind(_this);
    _this.isMobile = isMobile;
    return _this;
  }

  // eslint-disable-next-line camelcase
  _inherits(ReactImageLightbox, _Component);
  return _createClass(ReactImageLightbox, [{
    key: "UNSAFE_componentWillMount",
    value: function UNSAFE_componentWillMount() {
      // Timeouts - always clear it before umount
      this.timeouts = [];

      // Current action
      this.currentAction = ACTION_NONE;

      // Events source
      this.eventsSource = SOURCE_ANY;

      // Empty pointers list
      this.pointerList = [];

      // Prevent inner close
      this.preventInnerClose = false;
      this.preventInnerCloseTimeout = null;

      // Used to disable animation when changing props.mainSrc|nextSrc|prevSrc
      this.keyPressed = false;

      // Used to store load state / dimensions of images
      this.imageCache = {};

      // Time the last keydown event was called (used in keyboard action rate limiting)
      this.lastKeyDownTime = 0;

      // Used for debouncing window resize event
      this.resizeTimeout = null;

      // Used to determine when actions are triggered by the scroll wheel
      this.wheelActionTimeout = null;
      this.resetScrollTimeout = null;
      this.scrollX = 0;
      this.scrollY = 0;

      // Used in panning zoomed images
      this.moveStartX = 0;
      this.moveStartY = 0;
      this.moveStartOffsetX = 0;
      this.moveStartOffsetY = 0;

      // Used to swipe
      this.swipeStartX = 0;
      this.swipeStartY = 0;
      this.swipeEndX = 0;
      this.swipeEndY = 0;

      // Used to pinch
      this.pinchTouchList = null;
      this.pinchDistance = 0;

      // Used to differentiate between images with identical src
      this.keyCounter = 0;

      // Used to detect a move when all src's remain unchanged (four or more of the same image in a row)
      this.moveRequested = false;
      if (!this.props.animationDisabled) {
        // Make opening animation play
        this.setState({
          isClosing: false
        });
      }
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this2 = this;
      // Prevents cross-origin errors when using a cross-origin iframe
      this.windowContext = getHighestSafeWindowContext();
      this.listeners = {
        resize: this.handleWindowResize,
        mouseup: this.handleMouseUp,
        touchend: this.handleTouchEnd,
        touchcancel: this.handleTouchEnd,
        pointerdown: this.handlePointerEvent,
        pointermove: this.handlePointerEvent,
        pointerup: this.handlePointerEvent,
        pointercancel: this.handlePointerEvent
      };
      Object.keys(this.listeners).forEach(function (type) {
        _this2.windowContext.addEventListener(type, _this2.listeners[type]);
      });
      document.addEventListener('wheel', this.handleWheel, {
        passive: false
      });
      this.loadAllImages();
    }

    // eslint-disable-next-line camelcase
  }, {
    key: "UNSAFE_componentWillReceiveProps",
    value: function UNSAFE_componentWillReceiveProps(nextProps) {
      var _this3 = this;
      // Iterate through the source types for prevProps and nextProps to
      //  determine if any of the sources changed
      var sourcesChanged = false;
      var prevSrcDict = {};
      var nextSrcDict = {};
      this.getSrcTypes().forEach(function (srcType) {
        if (_this3.props[srcType.name] !== nextProps[srcType.name]) {
          sourcesChanged = true;
          prevSrcDict[_this3.props[srcType.name]] = true;
          nextSrcDict[nextProps[srcType.name]] = true;
        }
      });
      if (sourcesChanged || this.moveRequested) {
        // Reset the loaded state for images not rendered next
        Object.keys(prevSrcDict).forEach(function (prevSrc) {
          if (!(prevSrc in nextSrcDict) && prevSrc in _this3.imageCache) {
            _this3.imageCache[prevSrc].loaded = false;
          }
        });
        this.moveRequested = false;

        // Load any new images
        this.loadAllImages(nextProps);
      }
    }
  }, {
    key: "shouldComponentUpdate",
    value: function shouldComponentUpdate() {
      // Wait for move...
      return !this.moveRequested;
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      var _this4 = this;
      this.didUnmount = true;
      Object.keys(this.listeners).forEach(function (type) {
        _this4.windowContext.removeEventListener(type, _this4.listeners[type]);
      });
      document.removeEventListener('wheel', this.handleWheel, {
        passive: false
      });
      this.timeouts.forEach(function (tid) {
        return clearTimeout(tid);
      });
    }
  }, {
    key: "setTimeout",
    value: function (_setTimeout) {
      function setTimeout(_x, _x2) {
        return _setTimeout.apply(this, arguments);
      }
      setTimeout.toString = function () {
        return _setTimeout.toString();
      };
      return setTimeout;
    }(function (func, time) {
      var _this5 = this;
      var id = setTimeout(function () {
        _this5.timeouts = _this5.timeouts.filter(function (tid) {
          return tid !== id;
        });
        func();
      }, time);
      this.timeouts.push(id);
      return id;
    })
  }, {
    key: "setPreventInnerClose",
    value: function setPreventInnerClose() {
      var _this6 = this;
      if (this.preventInnerCloseTimeout) {
        this.clearTimeout(this.preventInnerCloseTimeout);
      }
      this.preventInnerClose = true;
      this.preventInnerCloseTimeout = this.setTimeout(function () {
        _this6.preventInnerClose = false;
        _this6.preventInnerCloseTimeout = null;
      }, 100);
    }

    // Get info for the best suited image to display with the given srcType
  }, {
    key: "getBestImageForType",
    value: function getBestImageForType(srcType) {
      var imageSrc = this.props[srcType];
      var fitSizes = {};
      if (this.isImageLoaded(imageSrc)) {
        // Use full-size image if available
        fitSizes = this.getFitSizes(this.imageCache[imageSrc].width, this.imageCache[imageSrc].height);
      } else if (this.isImageLoaded(this.props["".concat(srcType, "Thumbnail")])) {
        // Fall back to using thumbnail if the image has not been loaded
        imageSrc = this.props["".concat(srcType, "Thumbnail")];
        fitSizes = this.getFitSizes(this.imageCache[imageSrc].width, this.imageCache[imageSrc].height, true);
      } else {
        return null;
      }
      return {
        src: imageSrc,
        height: this.imageCache[imageSrc].height,
        width: this.imageCache[imageSrc].width,
        targetHeight: fitSizes.height,
        targetWidth: fitSizes.width
      };
    }

    // Get sizing for when an image is larger than the window
  }, {
    key: "getFitSizes",
    value: function getFitSizes(width, height, stretch) {
      var boxSize = this.getLightboxRect();
      // Padding (px) between the edge of the window and the lightbox
      var imagePadding = this.isMobile ? 0 : 70;
      var maxHeight = boxSize.height - imagePadding * 2;
      var maxWidth = boxSize.width - imagePadding * 2;
      if (!stretch) {
        maxHeight = Math.min(maxHeight, height);
        maxWidth = Math.min(maxWidth, width);
      }
      var maxRatio = maxWidth / maxHeight;
      var srcRatio = width / height;
      if (maxRatio > srcRatio) {
        // height is the constraining dimension of the photo
        return {
          width: width * maxHeight / height,
          height: maxHeight
        };
      }
      return {
        width: maxWidth,
        height: height * maxWidth / width
      };
    }
  }, {
    key: "getMaxOffsets",
    value: function getMaxOffsets() {
      var zoomLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.zoomLevel;
      var currentImageInfo = this.getBestImageForType('mainSrc');
      if (currentImageInfo === null) {
        return {
          maxX: 0,
          minX: 0,
          maxY: 0,
          minY: 0
        };
      }
      var boxSize = this.getLightboxRect();
      var zoomMultiplier = this.getZoomMultiplier(zoomLevel);
      var maxX = 0;
      if (zoomMultiplier * currentImageInfo.width - boxSize.width < 0) {
        // if there is still blank space in the X dimension, don't limit except to the opposite edge
        maxX = (boxSize.width - zoomMultiplier * currentImageInfo.width) / 2;
      } else {
        maxX = (zoomMultiplier * currentImageInfo.width - boxSize.width) / 2;
      }
      var maxY = 0;
      if (zoomMultiplier * currentImageInfo.height - boxSize.height < 0) {
        // if there is still blank space in the Y dimension, don't limit except to the opposite edge
        maxY = (boxSize.height - zoomMultiplier * currentImageInfo.height) / 2;
      } else {
        maxY = (zoomMultiplier * currentImageInfo.height - boxSize.height) / 2;
      }
      return {
        maxX: maxX,
        maxY: maxY,
        minX: -1 * maxX,
        minY: -1 * maxY
      };
    }

    // Get image src types
  }, {
    key: "getSrcTypes",
    value: function getSrcTypes() {
      return [{
        name: 'mainSrc',
        keyEnding: "i".concat(this.keyCounter)
      }, {
        name: 'mainSrcThumbnail',
        keyEnding: "t".concat(this.keyCounter)
      }, {
        name: 'nextSrc',
        keyEnding: "i".concat(this.keyCounter + 1)
      }, {
        name: 'nextSrcThumbnail',
        keyEnding: "t".concat(this.keyCounter + 1)
      }, {
        name: 'prevSrc',
        keyEnding: "i".concat(this.keyCounter - 1)
      }, {
        name: 'prevSrcThumbnail',
        keyEnding: "t".concat(this.keyCounter - 1)
      }];
    }

    /**
     * Get sizing when the image is scaled
     */
  }, {
    key: "getZoomMultiplier",
    value: function getZoomMultiplier() {
      var zoomLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.zoomLevel;
      return Math.pow(ZOOM_RATIO, zoomLevel);
    }

    /**
     * Get the size of the lightbox in pixels
     */
  }, {
    key: "getLightboxRect",
    value: function getLightboxRect() {
      if (this.outerEl.current) {
        return this.outerEl.current.getBoundingClientRect();
      }
      return {
        width: getWindowWidth(),
        height: getWindowHeight(),
        top: 0,
        right: 0,
        bottom: 0,
        left: 0
      };
    }
  }, {
    key: "clearTimeout",
    value: function (_clearTimeout) {
      function clearTimeout(_x3) {
        return _clearTimeout.apply(this, arguments);
      }
      clearTimeout.toString = function () {
        return _clearTimeout.toString();
      };
      return clearTimeout;
    }(function (id) {
      this.timeouts = this.timeouts.filter(function (tid) {
        return tid !== id;
      });
      clearTimeout(id);
    }

    // Change zoom level
    )
  }, {
    key: "changeZoom",
    value: function changeZoom(zoomLevel, clientX, clientY) {
      // Ignore if zoom disabled
      if (!this.props.enableZoom) {
        return;
      }

      // Constrain zoom level to the set bounds
      var nextZoomLevel = Math.max(MIN_ZOOM_LEVEL, Math.min(MAX_ZOOM_LEVEL, zoomLevel));

      // Ignore requests that don't change the zoom level
      if (nextZoomLevel === this.state.zoomLevel) {
        return;
      }
      if (nextZoomLevel === MIN_ZOOM_LEVEL) {
        // Snap back to center if zoomed all the way out
        this.setState({
          zoomLevel: nextZoomLevel,
          offsetX: 0,
          offsetY: 0
        });
        return;
      }
      var imageBaseSize = this.getBestImageForType('mainSrc');
      if (imageBaseSize === null) {
        return;
      }
      var currentZoomMultiplier = this.getZoomMultiplier();
      var nextZoomMultiplier = this.getZoomMultiplier(nextZoomLevel);

      // Default to the center of the image to zoom when no mouse position specified
      var boxRect = this.getLightboxRect();
      var pointerX = typeof clientX !== 'undefined' ? clientX - boxRect.left : boxRect.width / 2;
      var pointerY = typeof clientY !== 'undefined' ? clientY - boxRect.top : boxRect.height / 2;
      var currentImageOffsetX = (boxRect.width - imageBaseSize.width * currentZoomMultiplier) / 2;
      var currentImageOffsetY = (boxRect.height - imageBaseSize.height * currentZoomMultiplier) / 2;
      var currentImageRealOffsetX = currentImageOffsetX - this.state.offsetX;
      var currentImageRealOffsetY = currentImageOffsetY - this.state.offsetY;
      var currentPointerXRelativeToImage = (pointerX - currentImageRealOffsetX) / currentZoomMultiplier;
      var currentPointerYRelativeToImage = (pointerY - currentImageRealOffsetY) / currentZoomMultiplier;
      var nextImageRealOffsetX = pointerX - currentPointerXRelativeToImage * nextZoomMultiplier;
      var nextImageRealOffsetY = pointerY - currentPointerYRelativeToImage * nextZoomMultiplier;
      var nextImageOffsetX = (boxRect.width - imageBaseSize.width * nextZoomMultiplier) / 2;
      var nextImageOffsetY = (boxRect.height - imageBaseSize.height * nextZoomMultiplier) / 2;
      var nextOffsetX = nextImageOffsetX - nextImageRealOffsetX;
      var nextOffsetY = nextImageOffsetY - nextImageRealOffsetY;

      // When zooming out, limit the offset so things don't get left askew
      if (this.currentAction !== ACTION_PINCH) {
        var maxOffsets = this.getMaxOffsets();
        if (this.state.zoomLevel > nextZoomLevel) {
          nextOffsetX = Math.max(maxOffsets.minX, Math.min(maxOffsets.maxX, nextOffsetX));
          nextOffsetY = Math.max(maxOffsets.minY, Math.min(maxOffsets.maxY, nextOffsetY));
        }
      }
      this.setState({
        zoomLevel: nextZoomLevel,
        offsetX: nextOffsetX,
        offsetY: nextOffsetY
      });
    }
  }, {
    key: "closeIfClickInner",
    value: function closeIfClickInner(event) {
      if (!this.preventInnerClose && event.target.className.search(/\bril-inner\b/) > -1) {
        this.requestClose(event);
      }
    }

    /**
     * Handle user keyboard actions
     */
  }, {
    key: "handleKeyInput",
    value: function handleKeyInput(event) {
      event.stopPropagation();

      // Ignore key input during animations
      if (this.isAnimating()) {
        return;
      }

      // Allow slightly faster navigation through the images when user presses keys repeatedly
      if (event.type === 'keyup') {
        this.lastKeyDownTime -= this.props.keyRepeatKeyupBonus;
        return;
      }
      var keyCode = event.which || event.keyCode;

      // Ignore key presses that happen too close to each other (when rapid fire key pressing or holding down the key)
      // But allow it if it's a lightbox closing action
      var currentTime = new Date();
      if (currentTime.getTime() - this.lastKeyDownTime < this.props.keyRepeatLimit && keyCode !== KEYS.ESC) {
        return;
      }
      this.lastKeyDownTime = currentTime.getTime();
      switch (keyCode) {
        // ESC key closes the lightbox
        case KEYS.ESC:
          event.preventDefault();
          this.requestClose(event);
          break;

        // Left arrow key moves to previous image
        case KEYS.LEFT_ARROW:
          if (!this.props.prevSrc) {
            return;
          }
          event.preventDefault();
          this.keyPressed = true;
          this.requestMovePrev(event);
          break;

        // Right arrow key moves to next image
        case KEYS.RIGHT_ARROW:
          if (!this.props.nextSrc) {
            return;
          }
          event.preventDefault();
          this.keyPressed = true;
          this.requestMoveNext(event);
          break;

        // Up arrow key moves to upper row
        case KEYS.UP_ARROW:
          {
            if (this.props.onClickMoveUp) {
              event.preventDefault();
              this.keyPressed = true;
              this.requestMoveUp(event);
            }
            break;
          }
        // Down arrow key moves to down row
        case KEYS.DOWN_ARROW:
          {
            if (this.props.onClickMoveUp) {
              event.preventDefault();
              this.keyPressed = true;
              this.requestMoveDown(event);
            }
            break;
          }
      }
    }

    /**
     * Handle a mouse wheel event over the lightbox container
     */
  }, {
    key: "handleOuterMousewheel",
    value: function handleOuterMousewheel(event) {
      var _this7 = this;
      // Prevent scrolling of the background
      event.stopPropagation();
      this.clearTimeout(this.resetScrollTimeout);
      this.resetScrollTimeout = this.setTimeout(function () {
        _this7.scrollX = 0;
        _this7.scrollY = 0;
      }, 300);
    }
  }, {
    key: "handleImageMouseWheel",
    value: function handleImageMouseWheel(event) {
      // when gesture move up/down/left/right, event.deltaY is integer, move image
      if (parseInt(event.deltaY) === parseFloat(event.deltaY)) {
        if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
          var newOffsetY = this.state.offsetY + event.deltaY;
          newOffsetY = newOffsetY < 0 ? 0 : newOffsetY;
          this.setState({
            offsetY: newOffsetY
          });
        } else {
          var newOffsetX = this.state.offsetX + event.deltaX;
          newOffsetX = newOffsetX < 0 ? 0 : newOffsetX;
          this.setState({
            offsetX: newOffsetX
          });
        }
        return;
      }
      // when gesture zoom in or zoom out, event.deltaY is decimal, zoom image
      var yThreshold = WHEEL_MOVE_Y_THRESHOLD;
      if (Math.abs(event.deltaY) >= Math.abs(event.deltaX)) {
        event.stopPropagation();
        // If the vertical scroll amount was large enough, perform a zoom
        if (Math.abs(event.deltaY) < yThreshold) {
          return;
        }
        this.scrollX = 0;
        this.scrollY += event.deltaY;
        this.changeZoom(this.state.zoomLevel - event.deltaY, event.clientX, event.clientY);
      }
    }

    /**
     * Handle a double click on the current image
     */
  }, {
    key: "handleImageDoubleClick",
    value: function handleImageDoubleClick(event) {
      if (this.state.zoomLevel > MIN_ZOOM_LEVEL) {
        // A double click when zoomed in zooms all the way out
        this.changeZoom(MIN_ZOOM_LEVEL, event.clientX, event.clientY);
      } else {
        // A double click when zoomed all the way out zooms in
        this.changeZoom(this.state.zoomLevel + ZOOM_BUTTON_INCREMENT_SIZE, event.clientX, event.clientY);
      }
    }
  }, {
    key: "handleImageClick",
    value: function handleImageClick(event) {
      event.stopPropagation();
      event.nativeEvent.stopImmediatePropagation();
    }
  }, {
    key: "shouldHandleEvent",
    value: function shouldHandleEvent(source) {
      if (this.eventsSource === source) {
        return true;
      }
      if (this.eventsSource === SOURCE_ANY) {
        this.eventsSource = source;
        return true;
      }
      switch (source) {
        case SOURCE_MOUSE:
          return false;
        case SOURCE_TOUCH:
          this.eventsSource = SOURCE_TOUCH;
          this.filterPointersBySource();
          return true;
        case SOURCE_POINTER:
          if (this.eventsSource === SOURCE_MOUSE) {
            this.eventsSource = SOURCE_POINTER;
            this.filterPointersBySource();
            return true;
          }
          return false;
        default:
          return false;
      }
    }
  }, {
    key: "addPointer",
    value: function addPointer(pointer) {
      this.pointerList.push(pointer);
    }
  }, {
    key: "removePointer",
    value: function removePointer(pointer) {
      this.pointerList = this.pointerList.filter(function (_ref) {
        var id = _ref.id;
        return id !== pointer.id;
      });
    }
  }, {
    key: "filterPointersBySource",
    value: function filterPointersBySource() {
      var _this8 = this;
      this.pointerList = this.pointerList.filter(function (_ref2) {
        var source = _ref2.source;
        return source === _this8.eventsSource;
      });
    }
  }, {
    key: "handleMouseDown",
    value: function handleMouseDown(event) {
      if (this.shouldHandleEvent(SOURCE_MOUSE) && ReactImageLightbox.isTargetMatchImage(event.target)) {
        this.addPointer(ReactImageLightbox.parseMouseEvent(event));
        this.multiPointerStart(event);
      }
    }
  }, {
    key: "handleMouseMove",
    value: function handleMouseMove(event) {
      if (this.shouldHandleEvent(SOURCE_MOUSE)) {
        this.multiPointerMove(event, [ReactImageLightbox.parseMouseEvent(event)]);
      }
    }
  }, {
    key: "handleMouseUp",
    value: function handleMouseUp(event) {
      if (this.shouldHandleEvent(SOURCE_MOUSE)) {
        this.removePointer(ReactImageLightbox.parseMouseEvent(event));
        this.multiPointerEnd(event);
      }
    }
  }, {
    key: "handlePointerEvent",
    value: function handlePointerEvent(event) {
      if (this.shouldHandleEvent(SOURCE_POINTER)) {
        switch (event.type) {
          case 'pointerdown':
            if (ReactImageLightbox.isTargetMatchImage(event.target)) {
              this.addPointer(ReactImageLightbox.parsePointerEvent(event));
              this.multiPointerStart(event);
            }
            break;
          case 'pointermove':
            this.multiPointerMove(event, [ReactImageLightbox.parsePointerEvent(event)]);
            break;
          case 'pointerup':
          case 'pointercancel':
            this.removePointer(ReactImageLightbox.parsePointerEvent(event));
            this.multiPointerEnd(event);
            break;
        }
      }
    }
  }, {
    key: "handleTouchStart",
    value: function handleTouchStart(event) {
      var _this9 = this;
      if (this.shouldHandleEvent(SOURCE_TOUCH) && ReactImageLightbox.isTargetMatchImage(event.target)) {
        [].forEach.call(event.changedTouches, function (eventTouch) {
          return _this9.addPointer(ReactImageLightbox.parseTouchPointer(eventTouch));
        });
        this.multiPointerStart(event);
      }
    }
  }, {
    key: "handleTouchMove",
    value: function handleTouchMove(event) {
      if (this.shouldHandleEvent(SOURCE_TOUCH)) {
        this.multiPointerMove(event, [].map.call(event.changedTouches, function (eventTouch) {
          return ReactImageLightbox.parseTouchPointer(eventTouch);
        }));
      }
    }
  }, {
    key: "handleTouchEnd",
    value: function handleTouchEnd(event) {
      var _this0 = this;
      if (this.shouldHandleEvent(SOURCE_TOUCH)) {
        [].map.call(event.changedTouches, function (touch) {
          return _this0.removePointer(ReactImageLightbox.parseTouchPointer(touch));
        });
        this.multiPointerEnd(event);
      }
    }
  }, {
    key: "decideMoveOrSwipe",
    value: function decideMoveOrSwipe(pointer) {
      if (this.state.zoomLevel <= MIN_ZOOM_LEVEL) {
        this.handleSwipeStart(pointer);
      } else {
        this.handleMoveStart(pointer);
      }
    }
  }, {
    key: "multiPointerStart",
    value: function multiPointerStart(event) {
      this.handleEnd(null);
      switch (this.pointerList.length) {
        case 1:
          {
            event.preventDefault();
            this.decideMoveOrSwipe(this.pointerList[0]);
            break;
          }
        case 2:
          {
            event.preventDefault();
            this.handlePinchStart(this.pointerList);
            break;
          }
      }
    }
  }, {
    key: "multiPointerMove",
    value: function multiPointerMove(event, pointerList) {
      switch (this.currentAction) {
        case ACTION_MOVE:
          {
            event.preventDefault();
            this.handleMove(pointerList[0]);
            break;
          }
        case ACTION_SWIPE:
          {
            event.preventDefault();
            this.handleSwipe(pointerList[0]);
            break;
          }
        case ACTION_PINCH:
          {
            event.preventDefault();
            this.handlePinch(pointerList);
            break;
          }
      }
    }
  }, {
    key: "multiPointerEnd",
    value: function multiPointerEnd(event) {
      if (this.currentAction !== ACTION_NONE) {
        this.setPreventInnerClose();
        this.handleEnd(event);
      }
      switch (this.pointerList.length) {
        case 0:
          {
            this.eventsSource = SOURCE_ANY;
            break;
          }
        case 1:
          {
            event.preventDefault();
            this.decideMoveOrSwipe(this.pointerList[0]);
            break;
          }
        case 2:
          {
            event.preventDefault();
            this.handlePinchStart(this.pointerList);
            break;
          }
      }
    }
  }, {
    key: "handleEnd",
    value: function handleEnd(event) {
      switch (this.currentAction) {
        case ACTION_MOVE:
          this.handleMoveEnd(event);
          break;
        case ACTION_SWIPE:
          this.handleSwipeEnd(event);
          break;
        case ACTION_PINCH:
          this.handlePinchEnd(event);
          break;
      }
    }

    // Handle move start over the lightbox container
    // This happens:
    // - On a mouseDown event
    // - On a touchstart event
  }, {
    key: "handleMoveStart",
    value: function handleMoveStart(_ref3) {
      var clientX = _ref3.x,
        clientY = _ref3.y;
      if (!this.props.enableZoom) {
        return;
      }
      this.currentAction = ACTION_MOVE;
      this.moveStartX = clientX;
      this.moveStartY = clientY;
      this.moveStartOffsetX = this.state.offsetX;
      this.moveStartOffsetY = this.state.offsetY;
    }

    // Handle dragging over the lightbox container
    // This happens:
    // - After a mouseDown and before a mouseUp event
    // - After a touchstart and before a touchend event
  }, {
    key: "handleMove",
    value: function handleMove(_ref4) {
      var clientX = _ref4.x,
        clientY = _ref4.y;
      var newOffsetX = this.moveStartX - clientX + this.moveStartOffsetX;
      var newOffsetY = this.moveStartY - clientY + this.moveStartOffsetY;
      if (this.state.offsetX !== newOffsetX || this.state.offsetY !== newOffsetY) {
        this.setState({
          offsetX: newOffsetX,
          offsetY: newOffsetY
        });
      }
    }
  }, {
    key: "handleMoveEnd",
    value: function handleMoveEnd() {
      var _this1 = this;
      this.currentAction = ACTION_NONE;
      this.moveStartX = 0;
      this.moveStartY = 0;
      this.moveStartOffsetX = 0;
      this.moveStartOffsetY = 0;
      // Snap image back into frame if outside max offset range
      var maxOffsets = this.getMaxOffsets();
      var nextOffsetX = Math.max(maxOffsets.minX, Math.min(maxOffsets.maxX, this.state.offsetX));
      var nextOffsetY = Math.max(maxOffsets.minY, Math.min(maxOffsets.maxY, this.state.offsetY));
      if (nextOffsetX !== this.state.offsetX || nextOffsetY !== this.state.offsetY) {
        this.setState({
          offsetX: nextOffsetX,
          offsetY: nextOffsetY,
          shouldAnimate: true
        });
        this.setTimeout(function () {
          _this1.setState({
            shouldAnimate: false
          });
        }, this.props.animationDuration);
      }
    }
  }, {
    key: "handleSwipeStart",
    value: function handleSwipeStart(_ref5) {
      var clientX = _ref5.x,
        clientY = _ref5.y;
      this.currentAction = ACTION_SWIPE;
      this.swipeStartX = clientX;
      this.swipeStartY = clientY;
      this.swipeEndX = clientX;
      this.swipeEndY = clientY;
    }
  }, {
    key: "handleSwipe",
    value: function handleSwipe(_ref6) {
      var clientX = _ref6.x,
        clientY = _ref6.y;
      this.swipeEndX = clientX;
      this.swipeEndY = clientY;
    }
  }, {
    key: "handleSwipeEnd",
    value: function handleSwipeEnd(event) {
      var xDiff = this.swipeEndX - this.swipeStartX;
      var xDiffAbs = Math.abs(xDiff);
      var yDiffAbs = Math.abs(this.swipeEndY - this.swipeStartY);
      this.currentAction = ACTION_NONE;
      this.swipeStartX = 0;
      this.swipeStartY = 0;
      this.swipeEndX = 0;
      this.swipeEndY = 0;
      if (!event || this.isAnimating() || xDiffAbs < yDiffAbs * 1.5) {
        return;
      }
      if (xDiffAbs < MIN_SWIPE_DISTANCE) {
        var boxRect = this.getLightboxRect();
        if (xDiffAbs < boxRect.width / 4) {
          return;
        }
      }
      if (xDiff > 0 && this.props.prevSrc) {
        event.preventDefault();
        this.requestMovePrev();
      } else if (xDiff < 0 && this.props.nextSrc) {
        event.preventDefault();
        this.requestMoveNext();
      }
    }
  }, {
    key: "calculatePinchDistance",
    value: function calculatePinchDistance() {
      var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.pinchTouchList,
        _ref8 = _slicedToArray(_ref7, 2),
        a = _ref8[0],
        b = _ref8[1];
      return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
    }
  }, {
    key: "calculatePinchCenter",
    value: function calculatePinchCenter() {
      var _ref9 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.pinchTouchList,
        _ref0 = _slicedToArray(_ref9, 2),
        a = _ref0[0],
        b = _ref0[1];
      return {
        x: a.x - (a.x - b.x) / 2,
        y: a.y - (a.y - b.y) / 2
      };
    }
  }, {
    key: "handleWheel",
    value: function handleWheel(event) {
      var sidebar = document.querySelector('.thumbnail-sidebar');
      if (sidebar && sidebar.contains(event.target)) {
        return;
      }
      event.preventDefault();
    }
  }, {
    key: "handlePinchStart",
    value: function handlePinchStart(pointerList) {
      if (!this.props.enableZoom) {
        return;
      }
      this.currentAction = ACTION_PINCH;
      this.pinchTouchList = pointerList.map(function (_ref1) {
        var id = _ref1.id,
          x = _ref1.x,
          y = _ref1.y;
        return {
          id: id,
          x: x,
          y: y
        };
      });
      this.pinchDistance = this.calculatePinchDistance();
    }
  }, {
    key: "handlePinch",
    value: function handlePinch(pointerList) {
      this.pinchTouchList = this.pinchTouchList.map(function (oldPointer) {
        for (var i = 0; i < pointerList.length; i += 1) {
          if (pointerList[i].id === oldPointer.id) {
            return pointerList[i];
          }
        }
        return oldPointer;
      });
      var newDistance = this.calculatePinchDistance();
      var zoomLevel = this.state.zoomLevel + newDistance - this.pinchDistance;
      this.pinchDistance = newDistance;
      var _this$calculatePinchC = this.calculatePinchCenter(this.pinchTouchList),
        clientX = _this$calculatePinchC.x,
        clientY = _this$calculatePinchC.y;
      this.changeZoom(zoomLevel, clientX, clientY);
    }
  }, {
    key: "handlePinchEnd",
    value: function handlePinchEnd() {
      this.currentAction = ACTION_NONE;
      this.pinchTouchList = null;
      this.pinchDistance = 0;
    }

    // Handle the window resize event
  }, {
    key: "handleWindowResize",
    value: function handleWindowResize() {
      this.clearTimeout(this.resizeTimeout);
      this.resizeTimeout = this.setTimeout(this.forceUpdate.bind(this), 100);
    }
  }, {
    key: "handleZoomInButtonClick",
    value: function handleZoomInButtonClick() {
      var nextZoomLevel = this.state.zoomLevel + ZOOM_BUTTON_INCREMENT_SIZE;
      this.changeZoom(nextZoomLevel);
      if (nextZoomLevel === MAX_ZOOM_LEVEL) {
        this.zoomOutBtn.current.focus();
      }
    }
  }, {
    key: "handleZoomOutButtonClick",
    value: function handleZoomOutButtonClick() {
      var nextZoomLevel = this.state.zoomLevel - ZOOM_BUTTON_INCREMENT_SIZE;
      this.changeZoom(nextZoomLevel);
      if (nextZoomLevel === MIN_ZOOM_LEVEL) {
        this.zoomInBtn.current.focus();
      }
    }
  }, {
    key: "handleCaptionMousewheel",
    value: function handleCaptionMousewheel(event) {
      event.stopPropagation();
      if (!this.caption.current) {
        return;
      }
      var _this$caption$current = this.caption.current.getBoundingClientRect(),
        height = _this$caption$current.height;
      var _this$caption$current2 = this.caption.current,
        scrollHeight = _this$caption$current2.scrollHeight,
        scrollTop = _this$caption$current2.scrollTop;
      if (event.deltaY > 0 && height + scrollTop >= scrollHeight || event.deltaY < 0 && scrollTop <= 0) {
        event.preventDefault();
      }
    }

    // Detach key and mouse input events
  }, {
    key: "isAnimating",
    value: function isAnimating() {
      return this.state.shouldAnimate || this.state.isClosing;
    }

    // Check if image is loaded
  }, {
    key: "isImageLoaded",
    value: function isImageLoaded(imageSrc) {
      return imageSrc && imageSrc in this.imageCache && this.imageCache[imageSrc].loaded;
    }

    // Load image from src and call callback with image width and height on load
  }, {
    key: "loadImage",
    value: function loadImage(srcType, imageSrc, done) {
      var _this10 = this;
      // Return the image info if it is already cached
      if (this.isImageLoaded(imageSrc)) {
        this.setTimeout(function () {
          done();
        }, 1);
        return;
      }
      var inMemoryImage = new global.Image();
      if (this.props.imageCrossOrigin) {
        inMemoryImage.crossOrigin = this.props.imageCrossOrigin;
      }
      inMemoryImage.onerror = function (errorEvent) {
        _this10.props.onImageLoadError(imageSrc, srcType, errorEvent);

        // failed to load so set the state loadErrorStatus
        _this10.setState(function (prevState) {
          return {
            loadErrorStatus: _objectSpread2(_objectSpread2({}, prevState.loadErrorStatus), {}, _defineProperty({}, srcType, true))
          };
        });
        done(errorEvent);
      };
      inMemoryImage.onload = function () {
        _this10.props.onImageLoad(imageSrc, srcType, inMemoryImage);
        _this10.imageCache[imageSrc] = {
          loaded: true,
          width: inMemoryImage.width,
          height: inMemoryImage.height
        };
        done();
      };
      inMemoryImage.src = imageSrc;
    }

    // Load all images and their thumbnails
  }, {
    key: "loadAllImages",
    value: function loadAllImages() {
      var _this11 = this;
      var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
      var generateLoadDoneCallback = function generateLoadDoneCallback(srcType, imageSrc) {
        return function (err) {
          // Give up showing image on error
          if (err) {
            return;
          }

          // Don't rerender if the src is not the same as when the load started
          // or if the component has unmounted
          if (_this11.props[srcType] !== imageSrc || _this11.didUnmount) {
            return;
          }

          // Force rerender with the new image
          _this11.forceUpdate();
        };
      };

      // Load the images
      this.getSrcTypes().forEach(function (srcType) {
        var type = srcType.name;

        // there is no error when we try to load it initially
        if (props[type] && _this11.state.loadErrorStatus[type]) {
          _this11.setState(function (prevState) {
            return {
              loadErrorStatus: _objectSpread2(_objectSpread2({}, prevState.loadErrorStatus), {}, _defineProperty({}, type, false))
            };
          });
        }

        // Load unloaded images
        if (props[type] && !_this11.isImageLoaded(props[type])) {
          _this11.loadImage(type, props[type], generateLoadDoneCallback(type, props[type]));
        }
      });
    }

    // Request that the lightbox be closed
  }, {
    key: "requestClose",
    value: function requestClose(event) {
      var _this12 = this;
      // Call the parent close request
      var closeLightbox = function closeLightbox() {
        _this12.saveRotateImage();
        _this12.props.onCloseRequest(event);
      };
      if (this.props.animationDisabled || event.type === 'keydown' && !this.props.animationOnKeyInput) {
        // No animation
        closeLightbox();
        return;
      }

      // With animation
      // Start closing animation
      this.setState({
        isClosing: true
      });

      // Perform the actual closing at the end of the animation
      this.setTimeout(closeLightbox, this.props.animationDuration);
    }
  }, {
    key: "requestMove",
    value: function requestMove(direction, event) {
      var _this13 = this;
      // Reset the zoom level on image move
      var nextState = {
        zoomLevel: MIN_ZOOM_LEVEL,
        offsetX: 0,
        offsetY: 0
      };

      // Enable animated states
      if (!this.props.animationDisabled && (!this.keyPressed || this.props.animationOnKeyInput)) {
        nextState.shouldAnimate = true;
        this.setTimeout(function () {
          return _this13.setState({
            shouldAnimate: false
          });
        }, this.props.animationDuration);
      }
      this.keyPressed = false;
      this.moveRequested = true;
      this.saveRotateImage();
      if (direction === 'prev') {
        this.keyCounter -= 1;
        this.setState(nextState);
        this.props.onMovePrevRequest(event);
      } else if (direction === 'next') {
        this.keyCounter += 1;
        this.setState(nextState);
        this.props.onMoveNextRequest(event);
      } else if (direction === 'up') {
        this.keyCounter = 0;
        this.setState(nextState);
        this.props.onClickMoveUp(event);
      } else if (direction === 'down') {
        this.keyCounter = 0;
        this.setState(nextState);
        this.props.onClickMoveDown(event);
      }
    }

    // Request to transition to the next image
  }, {
    key: "requestMoveNext",
    value: function requestMoveNext(event) {
      this.requestMove('next', event);
    }

    // Request to transition to the previous image
  }, {
    key: "requestMovePrev",
    value: function requestMovePrev(event) {
      this.requestMove('prev', event);
    }

    // Request to transition to the up row image
  }, {
    key: "requestMoveUp",
    value: function requestMoveUp(event) {
      this.requestMove('up', event);
    }

    // Request to transition to the down row image
  }, {
    key: "requestMoveDown",
    value: function requestMoveDown(event) {
      this.requestMove('down', event);
    }
  }, {
    key: "saveRotateImage",
    value: function saveRotateImage() {
      if (this.props.onRotateImage && this.state.rotateDeg !== 0 && this.state.rotateDeg !== 360) {
        this.props.onRotateImage(this.state.rotateDeg);
        this.setState({
          rotateDeg: 0
        });
      }
    }
  }, {
    key: "rotateImage",
    value: function rotateImage() {
      var rotateDeg = this.state.rotateDeg;
      // Rotate the image counterclockwise, decreasing the angle by 90 degrees
      rotateDeg = rotateDeg - 90;
      if (rotateDeg < 0) {
        rotateDeg = rotateDeg + 360;
      }
      this.setState({
        rotateDeg: rotateDeg
      });
    }
  }, {
    key: "render",
    value: function render() {
      var _this14 = this;
      var _this$props = this.props,
        imageItems = _this$props.imageItems,
        currentIndex = _this$props.currentIndex,
        setImageIndex = _this$props.setImageIndex,
        animationDisabled = _this$props.animationDisabled,
        animationDuration = _this$props.animationDuration,
        clickOutsideToClose = _this$props.clickOutsideToClose,
        discourageDownloads = _this$props.discourageDownloads,
        enableZoom = _this$props.enableZoom,
        imageTitle = _this$props.imageTitle,
        nextSrc = _this$props.nextSrc,
        prevSrc = _this$props.prevSrc,
        toolbarButtons = _this$props.toolbarButtons,
        _onAfterOpen = _this$props.onAfterOpen,
        imageCrossOrigin = _this$props.imageCrossOrigin,
        reactModalProps = _this$props.reactModalProps,
        onRotateImage = _this$props.onRotateImage,
        onClickDownload = _this$props.onClickDownload,
        onClickDelete = _this$props.onClickDelete,
        onViewOriginal = _this$props.onViewOriginal,
        onClickMoveUp = _this$props.onClickMoveUp,
        onClickMoveDown = _this$props.onClickMoveDown,
        closeLabel = _this$props.closeLabel,
        downloadImageLabel = _this$props.downloadImageLabel,
        deleteImageLabel = _this$props.deleteImageLabel,
        zoomInLabel = _this$props.zoomInLabel,
        zoomOutLabel = _this$props.zoomOutLabel,
        viewOriginalImageLabel = _this$props.viewOriginalImageLabel,
        rotateImageLabel = _this$props.rotateImageLabel,
        onOCR = _this$props.onOCR,
        OCRLabel = _this$props.OCRLabel,
        sidePanel = _this$props.sidePanel,
        metadataLabel = _this$props.metadataLabel,
        onClickMetadata = _this$props.onClickMetadata;
      var _this$state = this.state,
        zoomLevel = _this$state.zoomLevel,
        offsetX = _this$state.offsetX,
        offsetY = _this$state.offsetY,
        isClosing = _this$state.isClosing,
        loadErrorStatus = _this$state.loadErrorStatus,
        rotateDeg = _this$state.rotateDeg;
      var boxSize = this.getLightboxRect();
      var transitionStyle = {};
      var isAnimating = this.isAnimating();

      // Transition settings for sliding animations
      if (!animationDisabled && isAnimating) {
        transitionStyle = _objectSpread2(_objectSpread2({}, transitionStyle), {}, {
          transition: "transform ".concat(animationDuration, "ms")
        });
      }

      // Key endings to differentiate between images with the same src
      var keyEndings = {};
      this.getSrcTypes().forEach(function (_ref10) {
        var name = _ref10.name,
          keyEnding = _ref10.keyEnding;
        keyEndings[name] = keyEnding;
      });

      // Images to be displayed
      var images = [];
      var addImage = function addImage(srcType, imageClass, transforms) {
        // Ignore types that have no source defined for their full size image
        if (!_this14.props[srcType]) {
          return;
        }
        var bestImageInfo = _this14.getBestImageForType(srcType);
        var imageStyle = _objectSpread2(_objectSpread2({}, transitionStyle), ReactImageLightbox.getTransform(_objectSpread2(_objectSpread2({}, transforms), bestImageInfo)));
        if (zoomLevel > MIN_ZOOM_LEVEL) {
          imageStyle.cursor = 'move';
        }
        imageStyle.transform = "".concat(imageStyle.transform, " rotate(").concat(rotateDeg, "deg)");
        // support IE 9 and 11
        var hasTrueValue = function hasTrueValue(object) {
          return Object.keys(object).some(function (key) {
            return object[key];
          });
        };

        // when error on one of the loads then push custom error stuff
        if (bestImageInfo === null && hasTrueValue(loadErrorStatus)) {
          images.push(/*#__PURE__*/React.createElement("div", {
            className: "".concat(imageClass, " ril__image ril-errored"),
            style: imageStyle,
            key: _this14.props[srcType] + keyEndings[srcType]
          }, /*#__PURE__*/React.createElement("div", {
            className: "ril__errorContainer"
          }, _this14.props.imageLoadErrorMessage)));
          return;
        }
        if (bestImageInfo === null) {
          var loadingIcon = /*#__PURE__*/React.createElement("div", {
            className: "ril-loading-circle ril__loadingCircle ril__loadingContainer__icon"
          }, _toConsumableArray(new Array(12)).map(function (_, index) {
            return /*#__PURE__*/React.createElement("div", {
              // eslint-disable-next-line react/no-array-index-key
              key: index,
              className: "ril-loading-circle-point ril__loadingCirclePoint"
            });
          }));

          // Fall back to loading icon if the thumbnail has not been loaded
          images.push(/*#__PURE__*/React.createElement("div", {
            className: "".concat(imageClass, " ril__image ril-not-loaded"),
            style: imageStyle,
            key: _this14.props[srcType] + keyEndings[srcType]
          }, /*#__PURE__*/React.createElement("div", {
            className: "ril__loadingContainer"
          }, loadingIcon)));
          return;
        }
        var imageSrc = bestImageInfo.src;
        if (discourageDownloads) {
          imageStyle.backgroundImage = "url('".concat(imageSrc, "')");
          images.push(/*#__PURE__*/React.createElement("div", {
            className: "".concat(imageClass, " ril__image ril__imageDiscourager"),
            onDoubleClick: _this14.handleImageDoubleClick,
            onWheel: _this14.handleImageMouseWheel,
            style: imageStyle,
            key: imageSrc + keyEndings[srcType]
          }, /*#__PURE__*/React.createElement("div", {
            className: "ril-download-blocker ril__downloadBlocker"
          })));
        } else {
          images.push(/*#__PURE__*/React.createElement("img", _extends({}, imageCrossOrigin ? {
            crossOrigin: imageCrossOrigin
          } : {}, {
            className: "".concat(imageClass, " ril__image"),
            onDoubleClick: _this14.handleImageDoubleClick,
            onClick: _this14.handleImageClick,
            onWheel: _this14.handleImageMouseWheel,
            onDragStart: function onDragStart(e) {
              return e.preventDefault();
            },
            style: imageStyle,
            src: imageSrc,
            key: imageSrc + keyEndings[srcType],
            alt: typeof imageTitle === 'string' ? imageTitle : translate('Image'),
            draggable: false
          })));
        }
      };
      var zoomMultiplier = this.getZoomMultiplier();
      // Next Image (displayed on the right)
      // addImage('nextSrc', 'ril-image-next ril__imageNext', {
      //   x: boxSize.width,
      // });
      // Main Image
      addImage('mainSrc', 'ril-image-current', {
        x: -1 * offsetX,
        y: -1 * offsetY,
        zoom: zoomMultiplier
      });
      // Previous Image (displayed on the left)
      // addImage('prevSrc', 'ril-image-prev ril__imagePrev', {
      //   x: -1 * boxSize.width,
      // });

      var reactModalStyle = Object.assign({}, {
        overlay: {
          zIndex: 1051,
          backgroundColor: this.isMobile ? '#000' : 'transparent'
        }
      }, this.props.reactModalStyle);
      var modalStyle = {
        overlay: _objectSpread2({
          zIndex: 1000,
          backgroundColor: 'transparent'
        }, reactModalStyle.overlay),
        content: _objectSpread2({
          backgroundColor: 'transparent',
          overflow: 'hidden',
          // Needed, otherwise keyboard shortcuts scroll the page
          border: 'none',
          borderRadius: 0,
          padding: 0,
          top: 0,
          left: 0,
          right: 0,
          bottom: 0
        }, reactModalStyle.content)
      };
      return /*#__PURE__*/React.createElement(Modal, _extends({
        isOpen: true,
        onRequestClose: clickOutsideToClose ? this.requestClose : undefined,
        onAfterOpen: function onAfterOpen() {
          // Focus on the div with key handlers
          if (_this14.outerEl.current) {
            _this14.outerEl.current.focus();
          }
          _onAfterOpen();
        },
        style: modalStyle,
        contentLabel: translate('Lightbox'),
        appElement: typeof global.window !== 'undefined' ? global.window.document.body : undefined
      }, reactModalProps), /*#__PURE__*/React.createElement("div", {
        // eslint-disable-line jsx-a11y/no-static-element-interactions
        // Floating modal with closing animations
        className: "ril-outer ril__outer ril__outerAnimating ".concat(this.props.wrapperClassName, " ").concat(isClosing ? 'ril-closing ril__outerClosing' : '', " ").concat(this.isMobile ? 'mobile-image-previewer' : 'PC-image-previewer'),
        style: {
          transition: "opacity ".concat(animationDuration, "ms"),
          animationDuration: "".concat(animationDuration, "ms"),
          animationDirection: isClosing ? 'normal' : 'reverse'
        },
        ref: this.outerEl,
        onWheel: this.handleOuterMousewheel,
        onMouseMove: this.handleMouseMove,
        onMouseDown: this.handleMouseDown,
        onTouchStart: this.handleTouchStart,
        onTouchMove: this.handleTouchMove,
        tabIndex: "-1" // Enables key handlers on div
        ,
        onKeyDown: this.handleKeyInput,
        onKeyUp: this.handleKeyInput
      }, !this.isMobile && imageItems && imageItems.length > 1 && /*#__PURE__*/React.createElement("div", {
        className: "ril-sidebar ril__sidebar"
      }, /*#__PURE__*/React.createElement(SidebarThumbnails, {
        imageItems: imageItems,
        currentIndex: currentIndex,
        setImageIndex: setImageIndex
      })), /*#__PURE__*/React.createElement("div", {
        // eslint-disable-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
        // Image holder
        className: "ril-inner ril__inner",
        onClick: clickOutsideToClose ? this.closeIfClickInner : undefined,
        style: sidePanel ? {
          right: sidePanel.width,
          transition: 'right 0.3s ease'
        } : {}
      }, images), sidePanel && sidePanel.render(), /*#__PURE__*/React.createElement("div", {
        // Lightbox toolbar
        className: "ril-toolbar ril__toolbar"
      }, /*#__PURE__*/React.createElement("ul", {
        className: "ril-toolbar-left ril__toolbarSide ril__toolbarLeftSide"
      }, /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("span", {
        className: "ril-toolbar__item__child ril__toolbarItemChild"
      }, imageTitle))), /*#__PURE__*/React.createElement("ul", {
        className: "ril-toolbar-right ril__toolbarSide ril__toolbarRightSide"
      }, toolbarButtons && toolbarButtons.map(function (button, i) {
        return /*#__PURE__*/React.createElement("li", {
          key: "button_".concat(i + 1),
          className: "ril-toolbar__item ril__toolbarItem"
        }, button);
      }), onClickMoveUp && !this.isMobile && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__upMoveButton",
        onClick: !isAnimating ? this.requestMoveUp : undefined
      })), onClickMoveDown && !this.isMobile && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__downMoveButton",
        onClick: !isAnimating ? this.requestMoveDown : undefined
      })), sidePanel && !this.isMobile && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        "aria-label": metadataLabel,
        className: "ril-metadata ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__openMetadataButton",
        onClick: onClickMetadata
      })), /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        // Lightbox close button
        type: "button",
        key: "close",
        "aria-label": closeLabel,
        className: "ril-close ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__closeButton",
        onClick: !isAnimating ? this.requestClose : undefined // Ignore clicks during animation
      })))), /*#__PURE__*/React.createElement("div", {
        // onWheel={this.handleCaptionMousewheel}
        onMouseDown: function onMouseDown(event) {
          return event.stopPropagation();
        },
        className: "ril-caption ril__caption"
        // ref={this.caption}
      }, enableZoom && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        // Lightbox zoom in button
        type: "button",
        key: "zoom-in",
        "aria-label": zoomInLabel,
        className: ['ril-zoom-in', 'ril__toolbarItemChild', 'ril__builtinButton', 'ril__zoomInButton'].concat(_toConsumableArray(zoomLevel === MAX_ZOOM_LEVEL ? ['ril__builtinButtonDisabled'] : [])).join(' '),
        ref: this.zoomInBtn,
        disabled: isAnimating || zoomLevel === MAX_ZOOM_LEVEL,
        onClick: !isAnimating && zoomLevel !== MAX_ZOOM_LEVEL ? this.handleZoomInButtonClick : undefined
      })), enableZoom && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        // Lightbox zoom out button
        type: "button",
        key: "zoom-out",
        "aria-label": zoomOutLabel,
        className: ['ril-zoom-out', 'ril__toolbarItemChild', 'ril__builtinButton', 'ril__zoomOutButton'].concat(_toConsumableArray(zoomLevel === MIN_ZOOM_LEVEL ? ['ril__builtinButtonDisabled'] : [])).join(' '),
        ref: this.zoomOutBtn,
        disabled: isAnimating || zoomLevel === MIN_ZOOM_LEVEL,
        onClick: !isAnimating && zoomLevel !== MIN_ZOOM_LEVEL ? this.handleZoomOutButtonClick : undefined
      })), onRotateImage && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        // Lightbox rotate button
        type: "button",
        "aria-label": rotateImageLabel,
        className: ['ril-rotate', 'ril__toolbarItemChild', 'ril__builtinButton', 'ril__rotateButton_2'].join(' '),
        style: {
          marginBottom: 4
        },
        onClick: this.rotateImage
      })), !this.isMobile && (onClickDownload || onClickDelete) && /*#__PURE__*/React.createElement("div", {
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__divider"
      }), onClickDownload && !this.isMobile && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        "aria-label": downloadImageLabel,
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__downloadButton",
        onClick: onClickDownload
      })), onClickDelete && !this.isMobile && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        "aria-label": deleteImageLabel,
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__deleteButton",
        onClick: onClickDelete
      })), !this.isMobile && (onViewOriginal || onOCR) && /*#__PURE__*/React.createElement("div", {
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__divider"
      }), onOCR && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        "aria-label": OCRLabel,
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__OCR",
        onClick: onOCR
      })), onViewOriginal && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem view-original-button"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        "aria-label": viewOriginalImageLabel,
        className: "ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__viewOriginalButton",
        onClick: onViewOriginal
      }, viewOriginalImageLabel)))), this.isMobile && /*#__PURE__*/React.createElement("div", {
        className: "image-footer-choice mobile-image-footer-choice"
      }, /*#__PURE__*/React.createElement("div", {
        className: "image-footer-icon"
      }, /*#__PURE__*/React.createElement("div", {
        className: "image-footer-right-icons"
      }, onRotateImage && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        style: {
          marginRight: '16px'
        },
        "aria-label": rotateImageLabel,
        className: ['ril-rotate', 'ril__toolbarItemChild', 'ril__builtinButton', 'ril__rotateButton', 'image-footer-choice-item'].join(' '),
        onClick: this.rotateImage
      })), onClickDownload && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        "aria-label": downloadImageLabel,
        className: ['ril-rotate', 'ril__toolbarItemChild', 'ril__builtinButton', 'ril__downloadButton', 'image-footer-choice-item'].join(' '),
        onClick: onClickDownload
      }))), onClickDelete && /*#__PURE__*/React.createElement("li", {
        className: "ril-toolbar__item ril__toolbarItem"
      }, /*#__PURE__*/React.createElement("button", {
        type: "button",
        "aria-label": deleteImageLabel,
        className: "ril-close ril-toolbar__item__child ril__toolbarItemChild ril__builtinButton ril__deleteButton image-footer-choice-item",
        onClick: onClickDelete
      })))));
    }
  }], [{
    key: "isTargetMatchImage",
    value: function isTargetMatchImage(target) {
      return target && /ril-image-current/.test(target.className);
    }
  }, {
    key: "parseMouseEvent",
    value: function parseMouseEvent(mouseEvent) {
      return {
        id: 'mouse',
        source: SOURCE_MOUSE,
        x: parseInt(mouseEvent.clientX, 10),
        y: parseInt(mouseEvent.clientY, 10)
      };
    }
  }, {
    key: "parseTouchPointer",
    value: function parseTouchPointer(touchPointer) {
      return {
        id: touchPointer.identifier,
        source: SOURCE_TOUCH,
        x: parseInt(touchPointer.clientX, 10),
        y: parseInt(touchPointer.clientY, 10)
      };
    }
  }, {
    key: "parsePointerEvent",
    value: function parsePointerEvent(pointerEvent) {
      return {
        id: pointerEvent.pointerId,
        source: SOURCE_POINTER,
        x: parseInt(pointerEvent.clientX, 10),
        y: parseInt(pointerEvent.clientY, 10)
      };
    }

    // Request to transition to the previous image
  }, {
    key: "getTransform",
    value: function getTransform(_ref11) {
      var _ref11$x = _ref11.x,
        x = _ref11$x === void 0 ? 0 : _ref11$x,
        _ref11$y = _ref11.y,
        y = _ref11$y === void 0 ? 0 : _ref11$y,
        _ref11$zoom = _ref11.zoom,
        zoom = _ref11$zoom === void 0 ? 1 : _ref11$zoom,
        width = _ref11.width,
        targetWidth = _ref11.targetWidth;
      var nextX = x;
      var windowWidth = getWindowWidth();
      if (width > windowWidth) {
        nextX += (windowWidth - width) / 2;
      }
      var scaleFactor = zoom * (targetWidth / width);
      return {
        transform: "translate3d(".concat(nextX, "px,").concat(y, "px,0) scale3d(").concat(scaleFactor, ",").concat(scaleFactor, ",1)")
      };
    }
  }]);
}(Component);
ReactImageLightbox.propTypes = {
  //-----------------------------
  // Image sources
  //-----------------------------

  currentIndex: PropTypes.number,
  setImageIndex: PropTypes.func,
  // Main display image url
  mainSrc: PropTypes.string.isRequired,
  // eslint-disable-line react/no-unused-prop-types

  // Previous display image url (displayed to the left)
  // If left undefined, movePrev actions will not be performed, and the button not displayed
  prevSrc: PropTypes.string,
  // Next display image url (displayed to the right)
  // If left undefined, moveNext actions will not be performed, and the button not displayed
  nextSrc: PropTypes.string,
  //-----------------------------
  // Image thumbnail sources
  //-----------------------------

  // Thumbnail image url corresponding to props.mainSrc
  mainSrcThumbnail: PropTypes.string,
  // eslint-disable-line react/no-unused-prop-types

  // Thumbnail image url corresponding to props.prevSrc
  prevSrcThumbnail: PropTypes.string,
  // eslint-disable-line react/no-unused-prop-types

  // Thumbnail image url corresponding to props.nextSrc
  nextSrcThumbnail: PropTypes.string,
  // eslint-disable-line react/no-unused-prop-types

  //-----------------------------
  // Event Handlers
  //-----------------------------

  // Close window event
  // Should change the parent state such that the lightbox is not rendered
  onCloseRequest: PropTypes.func.isRequired,
  // Move to previous image event
  // Should change the parent state such that props.prevSrc becomes props.mainSrc,
  //  props.mainSrc becomes props.nextSrc, etc.
  onMovePrevRequest: PropTypes.func,
  // Move to next image event
  // Should change the parent state such that props.nextSrc becomes props.mainSrc,
  //  props.mainSrc becomes props.prevSrc, etc.
  onMoveNextRequest: PropTypes.func,
  // Called when an image fails to load
  // (imageSrc: string, srcType: string, errorEvent: object): void
  onImageLoadError: PropTypes.func,
  // Called when image successfully loads
  onImageLoad: PropTypes.func,
  // Open window event
  onAfterOpen: PropTypes.func,
  onRotateImage: PropTypes.func,
  onClickMoveUp: PropTypes.func,
  onClickMoveDown: PropTypes.func,
  onClickDelete: PropTypes.func,
  onClickDownload: PropTypes.func,
  onViewOriginal: PropTypes.func,
  onClickMetadata: PropTypes.func,
  //-----------------------------
  // Download discouragement settings
  //-----------------------------

  // Enable download discouragement (prevents [right-click -> Save Image As...])
  discourageDownloads: PropTypes.bool,
  //-----------------------------
  // Animation settings
  //-----------------------------

  // Disable all animation
  animationDisabled: PropTypes.bool,
  // Disable animation on actions performed with keyboard shortcuts
  animationOnKeyInput: PropTypes.bool,
  // Animation duration (ms)
  animationDuration: PropTypes.number,
  //-----------------------------
  // Keyboard shortcut settings
  //-----------------------------

  // Required interval of time (ms) between key actions
  // (prevents excessively fast navigation of images)
  keyRepeatLimit: PropTypes.number,
  // Amount of time (ms) restored after each keyup
  // (makes rapid key presses slightly faster than holding down the key to navigate images)
  keyRepeatKeyupBonus: PropTypes.number,
  //-----------------------------
  // Image info
  //-----------------------------

  // Image title
  imageTitle: PropTypes.node,
  // Image caption
  imageCaption: PropTypes.node,
  // Optional crossOrigin attribute
  imageCrossOrigin: PropTypes.string,
  //-----------------------------
  // Lightbox style
  //-----------------------------

  // Set z-index style, etc., for the parent react-modal (format: https://github.com/reactjs/react-modal#styles )
  reactModalStyle: PropTypes.object,
  wrapperClassName: PropTypes.string,
  //-----------------------------
  // Other
  //-----------------------------

  // Array of custom toolbar buttons
  toolbarButtons: PropTypes.arrayOf(PropTypes.node),
  // When true, clicks outside of the image close the lightbox
  clickOutsideToClose: PropTypes.bool,
  // Set to false to disable zoom functionality and hide zoom buttons
  enableZoom: PropTypes.bool,
  // Override props set on react-modal (https://github.com/reactjs/react-modal)
  reactModalProps: PropTypes.shape({}),
  // Aria-labels
  nextLabel: PropTypes.string,
  prevLabel: PropTypes.string,
  zoomInLabel: PropTypes.string,
  zoomOutLabel: PropTypes.string,
  closeLabel: PropTypes.string,
  downloadImageLabel: PropTypes.string,
  deleteImageLabel: PropTypes.string,
  rotateImageLabel: PropTypes.string,
  viewOriginalImageLabel: PropTypes.string,
  metadataLabel: PropTypes.string,
  onOCR: PropTypes.func,
  OCRLabel: PropTypes.string,
  imageLoadErrorMessage: PropTypes.node,
  sidePanel: PropTypes.object
};
ReactImageLightbox.defaultProps = {
  imageItems: [],
  currentIndex: null,
  setImageIndex: function setImageIndex() {},
  imageTitle: null,
  imageCaption: null,
  toolbarButtons: null,
  reactModalProps: {},
  animationDisabled: false,
  animationDuration: 300,
  animationOnKeyInput: false,
  clickOutsideToClose: true,
  closeLabel: 'Close lightbox',
  discourageDownloads: false,
  enableZoom: true,
  imageCrossOrigin: null,
  keyRepeatKeyupBonus: 40,
  keyRepeatLimit: 180,
  mainSrcThumbnail: null,
  nextLabel: 'Next image',
  nextSrc: null,
  nextSrcThumbnail: null,
  onAfterOpen: function onAfterOpen() {},
  onImageLoadError: function onImageLoadError() {},
  onImageLoad: function onImageLoad() {},
  onMoveNextRequest: function onMoveNextRequest() {},
  onMovePrevRequest: function onMovePrevRequest() {},
  onClickMoveUp: null,
  onClickMoveDown: null,
  deleteImageLabel: 'Delete image',
  onClickDelete: null,
  downloadImageLabel: 'Download image',
  onClickDownload: null,
  onClickMetadata: null,
  prevLabel: 'Previous image',
  prevSrc: null,
  prevSrcThumbnail: null,
  reactModalStyle: {},
  wrapperClassName: '',
  zoomInLabel: 'Zoom in',
  zoomOutLabel: 'Zoom out',
  metadataLabel: 'Metadata',
  imageLoadErrorMessage: 'This image failed to load',
  onRotateImage: null,
  rotateImageLabel: 'Rotate image',
  onViewOriginal: null,
  viewOriginalImageLabel: 'View original image',
  onOCR: null,
  OCRLabel: 'OCR',
  sidePanel: null
};

export default ReactImageLightbox;
