react-accessible-lightbox
Version:
Lghtbox for React components or images
828 lines (814 loc) • 115 kB
JavaScript
!function(root, factory) {
"object" == typeof exports && "object" == typeof module ? module.exports = factory(require("react"), require("react-modal")) : "function" == typeof define && define.amd ? define([ "react", "react-modal" ], factory) : "object" == typeof exports ? exports.LightboxReact = factory(require("react"), require("react-modal")) : root.LightboxReact = factory(root.react, root["react-modal"]);
}(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_15__) {
/******/
return function(modules) {
/******/
/******/
// The require function
/******/
function __webpack_require__(moduleId) {
/******/
/******/
// Check if module is in cache
/******/
if (installedModules[moduleId]) /******/
return installedModules[moduleId].exports;
/******/
/******/
// Create a new module (and put it into the cache)
/******/
var module = installedModules[moduleId] = {
/******/
exports: {},
/******/
id: moduleId,
/******/
loaded: !1
};
/******/
/******/
// Return the exports of the module
/******/
/******/
/******/
// Execute the module function
/******/
/******/
/******/
// Flag the module as loaded
/******/
return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__),
module.loaded = !0, module.exports;
}
// webpackBootstrap
/******/
// The module cache
/******/
var installedModules = {};
/******/
/******/
// Load entry module and return exports
/******/
/******/
/******/
/******/
// expose the modules object (__webpack_modules__)
/******/
/******/
/******/
// expose the module cache
/******/
/******/
/******/
// __webpack_public_path__
/******/
return __webpack_require__.m = modules, __webpack_require__.c = installedModules,
__webpack_require__.p = "", __webpack_require__(0);
}([ /* 0 */
/***/
function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(3).default;
}, /* 1 */
/***/
function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
}, /* 2 */
/***/
function(module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
});
// Min image zoom level
exports.MIN_ZOOM_LEVEL = 0, exports.MAX_ZOOM_LEVEL = 300, exports.ZOOM_RATIO = 1.007,
exports.ZOOM_BUTTON_INCREMENT_SIZE = 100, exports.WHEEL_MOVE_X_THRESHOLD = 200,
exports.WHEEL_MOVE_Y_THRESHOLD = 1, exports.KEYS = {
ESC: 27,
LEFT_ARROW: 37,
RIGHT_ARROW: 39,
UP_ARROW: 38,
DOWN_ARROW: 40
}, exports.ACTION_NONE = 0, exports.ACTION_MOVE = 1, exports.ACTION_SWIPE = 2, exports.ACTION_PINCH = 3,
exports.ACTION_ROTATE = 4, exports.SOURCE_ANY = 0, exports.SOURCE_MOUSE = 1, exports.SOURCE_TOUCH = 2,
exports.SOURCE_POINTER = 3, exports.MIN_SWIPE_DISTANCE = 200;
}, /* 3 */
/***/
function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _defineProperty(obj, key, value) {
return key in obj ? Object.defineProperty(obj, key, {
value: value,
enumerable: !0,
configurable: !0,
writable: !0
}) : obj[key] = value, obj;
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
}
function _possibleConstructorReturn(self, call) {
if (!self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return !call || "object" != typeof call && "function" != typeof call ? self : call;
}
function _inherits(subClass, superClass) {
if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: !1,
writable: !0,
configurable: !0
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
Object.defineProperty(exports, "__esModule", {
value: !0
});
var _slicedToArray = function() {
function sliceIterator(arr, i) {
var _arr = [], _n = !0, _d = !1, _e = void 0;
try {
for (var _s, _i = arr[Symbol.iterator](); !(_n = (_s = _i.next()).done) && (_arr.push(_s.value),
!i || _arr.length !== i); _n = !0) ;
} catch (err) {
_d = !0, _e = err;
} finally {
try {
!_n && _i.return && _i.return();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function(arr, i) {
if (Array.isArray(arr)) return arr;
if (Symbol.iterator in Object(arr)) return sliceIterator(arr, i);
throw new TypeError("Invalid attempt to destructure non-iterable instance");
};
}(), _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || !1, descriptor.configurable = !0,
"value" in descriptor && (descriptor.writable = !0), Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
}(), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
}
return target;
}, _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(11), _propTypes2 = _interopRequireDefault(_propTypes), _reactModal = __webpack_require__(15), _reactModal2 = _interopRequireDefault(_reactModal), _isReact = __webpack_require__(9), _isReact2 = _interopRequireDefault(_isReact), _util = __webpack_require__(4), _constant = __webpack_require__(2), _style = __webpack_require__(14), _style2 = _interopRequireDefault(_style), styles = _style2.default, _ieVersion = (0,
_util.getIEVersion)();
_ieVersion < 10 && (styles = _extends({}, styles, {
toolbarSide: styles.toolbarSide + " " + styles.toolbarSideNoFlex,
toolbarLeftSide: styles.toolbarLeftSide + " " + styles.toolbarLeftSideNoFlex,
toolbarRightSide: styles.toolbarRightSide + " " + styles.toolbarRightSideNoFlex
}));
var LightboxReact = function(_Component) {
function LightboxReact(props) {
_classCallCheck(this, LightboxReact);
var _this = _possibleConstructorReturn(this, (LightboxReact.__proto__ || Object.getPrototypeOf(LightboxReact)).call(this, props));
return _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: !1,
//-----------------------------
// Zoom settings
//-----------------------------
// Zoom level of image
zoomLevel: _constant.MIN_ZOOM_LEVEL,
//-----------------------------
// Image position settings
//-----------------------------
// Horizontal offset from center
offsetX: 0,
// Vertical offset from center
offsetY: 0
}, _this.closeIfClickInner = _this.closeIfClickInner.bind(_this), _this.handleImageDoubleClick = _this.handleImageDoubleClick.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.handleKeyUpEventEvent = _this.handleKeyUpEventEvent.bind(_this),
_this;
}
return _inherits(LightboxReact, _Component), _createClass(LightboxReact, [ {
key: "componentWillMount",
value: function() {
// Timeouts - always clear it before umount
this.timeouts = [], // Current action
this.currentAction = _constant.ACTION_NONE, // Events source
this.eventsSource = _constant.SOURCE_ANY, // Empty pointers list
this.pointerList = [], // Prevent inner close
this.preventInnerClose = !1, this.preventInnerCloseTimeout = null, // Whether event listeners for keyboard and mouse input have been attached or not
this.listenersAttached = !1, // Used to disable animation when changing props.mainSrc|nextSrc|prevSrc
this.keyPressed = !1, // 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 = !1, this.props.animationDisabled || // Make opening animation play
this.setState({
isClosing: !1
});
}
}, {
key: "componentDidMount",
value: function() {
this.mounted = !0, this.attachListeners(), this.loadAllImages();
}
}, {
key: "shouldComponentUpdate",
value: function() {
// Wait for move...
return !this.moveRequested;
}
}, {
key: "componentWillReceiveProps",
value: function(nextProps) {
var _this2 = this, sourcesChanged = !1, prevSrcDict = {}, nextSrcDict = {};
this.getSrcTypes().forEach(function(srcType) {
_this2.props[srcType.name] !== nextProps[srcType.name] && (sourcesChanged = !0,
prevSrcDict[_this2.props[srcType.name]] = !0, nextSrcDict[nextProps[srcType.name]] = !0);
}), (sourcesChanged || this.moveRequested) && (// Reset the loaded state for images not rendered next
Object.keys(prevSrcDict).forEach(function(prevSrc) {
!(prevSrc in nextSrcDict) && prevSrc in _this2.imageCache && (_this2.imageCache[prevSrc].loaded = !1);
}), this.moveRequested = !1, // Load any new images
this.loadAllImages(nextProps));
}
}, {
key: "componentWillUnmount",
value: function() {
this.mounted = !1, this.detachListeners(), this.timeouts.forEach(function(tid) {
return clearTimeout(tid);
});
}
}, {
key: "setTimeout",
value: function(_setTimeout) {
function setTimeout(_x, _x2) {
return _setTimeout.apply(this, arguments);
}
return setTimeout.toString = function() {
return _setTimeout.toString();
}, setTimeout;
}(function(func, time) {
var _this3 = this, id = setTimeout(function() {
_this3.timeouts = _this3.timeouts.filter(function(tid) {
return tid !== id;
}), func();
}, time);
return this.timeouts.push(id), id;
})
}, {
key: "clearTimeout",
value: function(_clearTimeout) {
function clearTimeout(_x3) {
return _clearTimeout.apply(this, arguments);
}
return clearTimeout.toString = function() {
return _clearTimeout.toString();
}, clearTimeout;
}(function(id) {
this.timeouts = this.timeouts.filter(function(tid) {
return tid !== id;
}), clearTimeout(id);
})
}, {
key: "attachListeners",
value: function() {
this.listenersAttached || "undefined" == typeof window || (window.addEventListener("resize", this.handleWindowResize),
window.addEventListener("mouseup", this.handleMouseUp), window.addEventListener("touchend", this.handleTouchEnd),
window.addEventListener("touchcancel", this.handleTouchEnd), window.addEventListener("pointerdown", this.handlePointerEvent),
window.addEventListener("pointermove", this.handlePointerEvent), window.addEventListener("pointerup", this.handlePointerEvent),
window.addEventListener("pointercancel", this.handlePointerEvent), window.top.addEventListener("keydown", this.handleKeyUpEventEvent),
// Have to add an extra mouseup handler to catch mouseup events outside of the window
// if the page containing the lightbox is displayed in an iframe
(0, _util.isInSameOriginIframe)() && (window.top.addEventListener("mouseup", this.handleMouseUp),
window.top.addEventListener("touchend", this.handleTouchEnd), window.top.addEventListener("touchcancel", this.handleTouchEnd),
window.top.addEventListener("pointerdown", this.handlePointerEvent), window.top.addEventListener("pointermove", this.handlePointerEvent),
window.top.addEventListener("pointerup", this.handlePointerEvent), window.top.addEventListener("pointercancel", this.handlePointerEvent),
window.top.addEventListener("keydown", this.handleKeyUpEventEvent)), this.listenersAttached = !0);
}
}, {
key: "changeZoom",
value: function(zoomLevel, clientX, clientY) {
// Ignore if zoom disabled
if (this.props.enableZoom) {
// Constrain zoom level to the set bounds
var nextZoomLevel = Math.max(_constant.MIN_ZOOM_LEVEL, Math.min(_constant.MAX_ZOOM_LEVEL, zoomLevel));
// Ignore requests that don't change the zoom level
if (nextZoomLevel !== this.state.zoomLevel) {
if (nextZoomLevel === _constant.MIN_ZOOM_LEVEL) // Snap back to center if zoomed all the way out
return this.setState({
zoomLevel: nextZoomLevel,
offsetX: 0,
offsetY: 0
});
var imageBaseSize = this.getBestImageForType("mainSrc");
if (null !== imageBaseSize) {
var currentZoomMultiplier = this.getZoomMultiplier(), nextZoomMultiplier = this.getZoomMultiplier(nextZoomLevel), boxRect = this.getLightboxRect(), pointerX = "undefined" != typeof clientX ? clientX - boxRect.left : boxRect.width / 2, pointerY = "undefined" != typeof clientY ? clientY - boxRect.top : boxRect.height / 2, currentImageOffsetX = (boxRect.width - imageBaseSize.width * currentZoomMultiplier) / 2, currentImageOffsetY = (boxRect.height - imageBaseSize.height * currentZoomMultiplier) / 2, currentImageRealOffsetX = currentImageOffsetX - this.state.offsetX, currentImageRealOffsetY = currentImageOffsetY - this.state.offsetY, currentPointerXRelativeToImage = (pointerX - currentImageRealOffsetX) / currentZoomMultiplier, currentPointerYRelativeToImage = (pointerY - currentImageRealOffsetY) / currentZoomMultiplier, nextImageRealOffsetX = pointerX - currentPointerXRelativeToImage * nextZoomMultiplier, nextImageRealOffsetY = pointerY - currentPointerYRelativeToImage * nextZoomMultiplier, nextImageOffsetX = (boxRect.width - imageBaseSize.width * nextZoomMultiplier) / 2, nextImageOffsetY = (boxRect.height - imageBaseSize.height * nextZoomMultiplier) / 2, nextOffsetX = nextImageOffsetX - nextImageRealOffsetX, nextOffsetY = nextImageOffsetY - nextImageRealOffsetY;
// When zooming out, limit the offset so things don't get left askew
if (this.currentAction !== _constant.ACTION_PINCH) {
var maxOffsets = this.getMaxOffsets();
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(event) {
!this.preventInnerClose && event.target.className.search(/\bril-inner\b/) > -1 && this.requestClose(event);
}
}, {
key: "setPreventInnerClose",
value: function() {
var _this4 = this;
this.preventInnerCloseTimeout && this.clearTimeout(this.preventInnerCloseTimeout),
this.preventInnerClose = !0, this.preventInnerCloseTimeout = this.setTimeout(function() {
_this4.preventInnerClose = !1, _this4.preventInnerCloseTimeout = null;
}, 100);
}
}, {
key: "detachListeners",
value: function() {
this.listenersAttached && (window.removeEventListener("resize", this.handleWindowResize),
window.removeEventListener("keydown", this.handleKeyUpEventEvent), window.removeEventListener("mouseup", this.handleMouseUp),
window.removeEventListener("touchend", this.handleTouchEnd), window.removeEventListener("touchcancel", this.handleTouchEnd),
window.removeEventListener("pointerdown", this.handlePointerEvent), window.removeEventListener("pointermove", this.handlePointerEvent),
window.removeEventListener("pointerup", this.handlePointerEvent), window.removeEventListener("pointercancel", this.handlePointerEvent),
(0, _util.isInSameOriginIframe)() && (window.top.removeEventListener("mouseup", this.handleMouseUp),
window.top.removeEventListener("touchend", this.handleTouchEnd), window.top.removeEventListener("touchcancel", this.handleTouchEnd),
window.top.removeEventListener("pointerdown", this.handlePointerEvent), window.top.removeEventListener("pointermove", this.handlePointerEvent),
window.top.removeEventListener("pointerup", this.handlePointerEvent), window.top.removeEventListener("pointercancel", this.handlePointerEvent),
window.top.removeEventListener("keydown", this.handleKeyUpEventEvent)), this.listenersAttached = !1);
}
}, {
key: "getBestImageForType",
value: function(srcType) {
var imageSrc = this.props[srcType], 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[srcType + "Thumbnail"])) // Fall back to using thumbnail if the image has not been loaded
imageSrc = this.props[srcType + "Thumbnail"], fitSizes = this.getFitSizes(this.imageCache[imageSrc].width, this.imageCache[imageSrc].height, !0); else {
if (!_isReact2.default.component(this.props[srcType]) && !_isReact2.default.element(this.props[srcType])) return null;
if (document.querySelectorAll(".inner").length > 0 && !(this.state.zoomLevel > _constant.MIN_ZOOM_LEVEL)) {
var theCanvases = this.props.prevSrc && this.props.nextSrc ? document.querySelectorAll(".inner")[0].childNodes[1].childNodes[0] : document.querySelectorAll(".inner")[0].childNodes[0].childNodes[0], maxWidth = 900, aCanvasO = theCanvases, theTableO = aCanvasO.getElementsByTagName("table")[0];
// Get the 1st table (should be the only table)
//var spacerO = aCanvasO.nextElementSibling
// Remove any leftover scaling and spacer sizes - important for viewport resizing
theTableO.style.transform = "", theTableO.style.position = "relative", // spacerO.style.height = ''
// Pop open each .scaling-canvas to see how big the table becomes
// IMPORTANT: '.scaling-canvas table:first-child' MUST have 'position: absolute' defined in CSS
// in order for wide tables to not influence measurements on intial page load
aCanvasO.style.position = "absolute", aCanvasO.style.width = maxWidth + "px";
// }
// Next, we take measurements and scale the tables if needed
// for (var i = 0; i < arrayLength; i++) {
var aCanvas = theCanvases, theTable = aCanvas.getElementsByTagName("table")[0], spacer = document.querySelectorAll(".inner")[0].childNodes[0], availableWidth = Math.floor(spacer.clientWidth), actualTableWidth = theTable.offsetWidth, actualTableHeight = theTable.offsetHeight, computedStyle = getComputedStyle(theTable);
// Measure all table values in pixels
actualTableWidth += Math.ceil(parseInt(computedStyle.marginLeft) + parseInt(computedStyle.marginRight)),
actualTableHeight += Math.ceil(parseInt(computedStyle.marginTop) + parseInt(computedStyle.marginBottom));
// Calculate the scaling factor
var scale = availableWidth / actualTableWidth;
// If the scale is < 1, then scale the table, otherwise put .scaling-canvas back to defaults
scale < 1 ? (// Scale the table
// We hard-set the table width and height here so that it's not recalculated later
theTable.style.width = actualTableWidth + "px", theTable.style.transformOrigin = "top left",
theTable.style.transform = "scale(" + scale + ")", // Size the spacing container to provide proper vertical spacing.
// Its width defaults to 'auto' so no need to adjust that.
spacer.style.height = actualTableHeight * scale + "px", // Reposition the zoom button
// Size the canvas - in case overflow: hidden is not on parent
aCanvas.style.height = actualTableHeight * scale + "px", aCanvas.style.width = availableWidth + "px") : (// Set the scaling canvas back to defaults
aCanvas.style.position = "relative", aCanvas.style.width = ""), // let componentWidth = component.offsetWidth;
// let componentWrapperWidth = document.querySelectorAll('.inner')[0].childNodes[0].offsetWidth;
// let fontSize = 18;
//
// while (componentWidth >= componentWrapperWidth && fontSize > 4) {
// component.style.fontSize = `${fontSize}px`;
// componentWidth = component.offsetWidth;
// componentWrapperWidth = document.querySelectorAll('.inner')[0].childNodes[0].offsetWidth;
// fontSize--;
// }
fitSizes = this.getFitSizes(theCanvases.style.width, theCanvases.style.height);
} else if (document.querySelectorAll(".inner").length > 0) {
var _theCanvases = this.props.prevSrc && this.props.nextSrc ? document.querySelectorAll(".inner")[0].childNodes[1].childNodes[0] : document.querySelectorAll(".inner")[0].childNodes[0].childNodes[0];
fitSizes = this.getFitSizes(_theCanvases.offsetWidth, _theCanvases.offsetHeight);
}
}
return {
src: imageSrc,
height: fitSizes.height,
width: fitSizes.width
};
}
}, {
key: "getFitSizes",
value: function(width, height, stretch) {
var boxSize = this.getLightboxRect(), maxHeight = boxSize.height - 2 * this.props.imagePadding, maxWidth = boxSize.width - 2 * this.props.imagePadding;
stretch || (maxHeight = Math.min(maxHeight, height), maxWidth = Math.min(maxWidth, width));
var maxRatio = maxWidth / maxHeight, srcRatio = width / height;
return maxRatio > srcRatio ? {
width: width * maxHeight / height,
height: maxHeight
} : {
width: maxWidth,
height: height * maxWidth / width
};
}
}, {
key: "getMaxOffsets",
value: function() {
var zoomLevel = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : this.state.zoomLevel, currentImageInfo = this.getBestImageForType("mainSrc");
if (null === currentImageInfo) return {
maxX: 0,
minX: 0,
maxY: 0,
minY: 0
};
var boxSize = this.getLightboxRect(), zoomMultiplier = this.getZoomMultiplier(zoomLevel), maxX = 0;
// if there is still blank space in the X dimension, don't limit except to the opposite edge
maxX = zoomMultiplier * currentImageInfo.width - boxSize.width < 0 ? (boxSize.width - zoomMultiplier * currentImageInfo.width) / 2 : (zoomMultiplier * currentImageInfo.width - boxSize.width) / 2;
var maxY = 0;
// if there is still blank space in the Y dimension, don't limit except to the opposite edge
return maxY = zoomMultiplier * currentImageInfo.height - boxSize.height < 0 ? (boxSize.height - zoomMultiplier * currentImageInfo.height) / 2 : (zoomMultiplier * currentImageInfo.height - boxSize.height) / 2,
{
maxX: maxX,
maxY: maxY,
minX: -1 * maxX,
minY: -1 * maxY
};
}
}, {
key: "getSrcTypes",
value: function() {
return [ {
name: "mainSrc",
keyEnding: "i" + this.keyCounter
}, {
name: "mainSrcThumbnail",
keyEnding: "t" + this.keyCounter
}, {
name: "nextSrc",
keyEnding: "i" + (this.keyCounter + 1)
}, {
name: "nextSrcThumbnail",
keyEnding: "t" + (this.keyCounter + 1)
}, {
name: "prevSrc",
keyEnding: "i" + (this.keyCounter - 1)
}, {
name: "prevSrcThumbnail",
keyEnding: "t" + (this.keyCounter - 1)
} ];
}
}, {
key: "getZoomMultiplier",
value: function() {
var zoomLevel = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : this.state.zoomLevel;
return Math.pow(_constant.ZOOM_RATIO, zoomLevel);
}
}, {
key: "getLightboxRect",
value: function() {
return this.outerEl ? this.outerEl.getBoundingClientRect() : {
width: (0, _util.getWindowWidth)(),
height: (0, _util.getWindowHeight)(),
top: 0,
right: 0,
bottom: 0,
left: 0
};
}
}, {
key: "handleKeyInput",
value: function(event) {
// this will prevent key up event in order to avoid that commented this
//event.stopPropagation();
// Ignore key input during animations
if (!this.isAnimating()) {
// Allow slightly faster navigation through the images when user presses keys repeatedly
if ("keyup" === event.type) return void (this.lastKeyDownTime -= this.props.keyRepeatKeyupBonus);
var keyCode = event.which || event.keyCode, currentTime = new Date();
if (!(currentTime.getTime() - this.lastKeyDownTime < this.props.keyRepeatLimit && keyCode !== _constant.KEYS.ESC)) switch (this.lastKeyDownTime = currentTime.getTime(),
keyCode) {
// ESC key closes the lightbox
case _constant.KEYS.ESC:
event.preventDefault(), this.requestClose(event);
break;
// Left arrow key moves to previous image
case _constant.KEYS.LEFT_ARROW:
if (!this.props.prevSrc || this.state.zoomLevel !== _constant.MIN_ZOOM_LEVEL) return;
event.preventDefault(), this.keyPressed = !0, this.requestMovePrev(event);
break;
// Right arrow key moves to next image
case _constant.KEYS.RIGHT_ARROW:
if (!this.props.nextSrc || this.state.zoomLevel !== _constant.MIN_ZOOM_LEVEL) return;
event.preventDefault(), this.keyPressed = !0, this.requestMoveNext(event);
}
}
}
}, {
key: "handleOuterMousewheel",
value: function(event) {
var _this5 = this;
// Prevent scrolling of the background
event.preventDefault(), event.stopPropagation();
var xThreshold = _constant.WHEEL_MOVE_X_THRESHOLD, actionDelay = 0, imageMoveDelay = 500;
// Prevent rapid-fire zoom behavior
if (this.clearTimeout(this.resetScrollTimeout), this.resetScrollTimeout = this.setTimeout(function() {
_this5.scrollX = 0, _this5.scrollY = 0;
}, 300), null === this.wheelActionTimeout && !this.isAnimating()) {
if (Math.abs(event.deltaY) < Math.abs(event.deltaX)) {
// handle horizontal scrolls with image moves
this.scrollY = 0, this.scrollX += event.deltaX;
var bigLeapX = xThreshold / 2;
// If the scroll amount has accumulated sufficiently, or a large leap was taken
this.scrollX >= xThreshold || event.deltaX >= bigLeapX ? (// Scroll right moves to next
this.requestMoveNext(event), actionDelay = imageMoveDelay, this.scrollX = 0) : (this.scrollX <= -1 * xThreshold || event.deltaX <= -1 * bigLeapX) && (// Scroll left moves to previous
this.requestMovePrev(event), actionDelay = imageMoveDelay, this.scrollX = 0);
}
// Allow successive actions after the set delay
0 !== actionDelay && (this.wheelActionTimeout = this.setTimeout(function() {
_this5.wheelActionTimeout = null;
}, actionDelay));
}
}
}, {
key: "handleImageMouseWheel",
value: function(event) {
event.preventDefault();
var yThreshold = _constant.WHEEL_MOVE_Y_THRESHOLD;
if (Math.abs(event.deltaY) >= Math.abs(event.deltaX)) {
// If the vertical scroll amount was large enough, perform a zoom
if (event.stopPropagation(), Math.abs(event.deltaY) < yThreshold) return;
this.scrollX = 0, this.scrollY += event.deltaY, this.changeZoom(this.state.zoomLevel - event.deltaY, event.clientX, event.clientY);
}
}
}, {
key: "handleImageDoubleClick",
value: function(event) {
this.state.zoomLevel > _constant.MIN_ZOOM_LEVEL ? // A double click when zoomed in zooms all the way out
this.changeZoom(_constant.MIN_ZOOM_LEVEL, event.clientX, event.clientY) : // A double click when zoomed all the way out zooms in
this.changeZoom(this.state.zoomLevel + _constant.ZOOM_BUTTON_INCREMENT_SIZE, event.clientX, event.clientY);
}
}, {
key: "shouldHandleEvent",
value: function(source) {
if (this.eventsSource === source) return !0;
if (this.eventsSource === _constant.SOURCE_ANY) return this.eventsSource = source,
!0;
switch (source) {
case _constant.SOURCE_MOUSE:
return !1;
case _constant.SOURCE_TOUCH:
return this.eventsSource = _constant.SOURCE_TOUCH, this.filterPointersBySource(),
!0;
case _constant.SOURCE_POINTER:
return this.eventsSource === _constant.SOURCE_MOUSE && (this.eventsSource = _constant.SOURCE_POINTER,
this.filterPointersBySource(), !0);
default:
return !1;
}
}
}, {
key: "addPointer",
value: function(pointer) {
this.pointerList.push(pointer);
}
}, {
key: "removePointer",
value: function(pointer) {
this.pointerList = this.pointerList.filter(function(_ref) {
var id = _ref.id;
return id !== pointer.id;
});
}
}, {
key: "filterPointersBySource",
value: function() {
var _this6 = this;
this.pointerList = this.pointerList.filter(function(_ref2) {
var source = _ref2.source;
return source === _this6.eventsSource;
});
}
}, {
key: "handleMouseDown",
value: function(event) {
// remove isTargetMatchImage
this.shouldHandleEvent(_constant.SOURCE_MOUSE) && (this.addPointer(LightboxReact.parseMouseEvent(event)),
this.multiPointerStart(event));
}
}, {
key: "handleMouseMove",
value: function(event) {
this.shouldHandleEvent(_constant.SOURCE_MOUSE) && LightboxReact.isTargetMatchImage(event.target) && this.multiPointerMove(event, [ LightboxReact.parseMouseEvent(event) ]);
}
}, {
key: "handleMouseUp",
value: function(event) {
this.shouldHandleEvent(_constant.SOURCE_MOUSE) && (this.removePointer(LightboxReact.parseMouseEvent(event)),
this.multiPointerEnd(event));
}
}, {
key: "handlePointerEvent",
value: function(event) {
if (this.shouldHandleEvent(_constant.SOURCE_POINTER)) switch (event.type) {
case "pointerdown":
// commented this to facilitate to drag the tables after zooming
this.addPointer(LightboxReact.parsePointerEvent(event)), this.multiPointerStart(event);
break;
case "pointermove":
this.multiPointerMove(event, [ LightboxReact.parsePointerEvent(event) ]);
break;
case "pointerup":
case "pointercancel":
this.removePointer(LightboxReact.parsePointerEvent(event)), this.multiPointerEnd(event);
}
}
}, {
key: "handleTouchStart",
value: function(event) {
var _this7 = this;
this.shouldHandleEvent(_constant.SOURCE_TOUCH) && LightboxReact.isTargetMatchImage(event.target) && ([].forEach.call(event.changedTouches, function(eventTouch) {
return _this7.addPointer(LightboxReact.parseTouchPointer(eventTouch));
}), this.multiPointerStart(event));
}
}, {
key: "handleTouchMove",
value: function(event) {
event.preventDefault(), this.shouldHandleEvent(_constant.SOURCE_TOUCH) && this.multiPointerMove(event, [].map.call(event.changedTouches, function(eventTouch) {
return LightboxReact.parseTouchPointer(eventTouch);
}));
}
}, {
key: "handleTouchEnd",
value: function(event) {
var _this8 = this;
this.shouldHandleEvent(_constant.SOURCE_TOUCH) && ([].map.call(event.changedTouches, function(touch) {
return _this8.removePointer(LightboxReact.parseTouchPointer(touch));
}), this.multiPointerEnd(event));
}
}, {
key: "decideMoveOrSwipe",
value: function(pointer) {
this.state.zoomLevel <= _constant.MIN_ZOOM_LEVEL ? this.handleSwipeStart(pointer) : this.handleMoveStart(pointer);
}
}, {
key: "multiPointerStart",
value: function(event) {
switch (this.handleEnd(null), this.pointerList.length) {
case 1:
event.preventDefault(), this.decideMoveOrSwipe(this.pointerList[0]);
break;
case 2:
event.preventDefault(), this.handlePinchStart(this.pointerList);
}
}
}, {
key: "multiPointerMove",
value: function(event, pointerList) {
switch (this.currentAction) {
case _constant.ACTION_MOVE:
event.preventDefault(), this.handleMove(pointerList[0]);
break;
case _constant.ACTION_SWIPE:
event.preventDefault(), this.handleSwipe(pointerList[0]);
break;
case _constant.ACTION_PINCH:
event.preventDefault(), this.handlePinch(pointerList);
}
}
}, {
key: "multiPointerEnd",
value: function(event) {
switch (this.currentAction !== _constant.ACTION_NONE && (this.setPreventInnerClose(),
this.handleEnd(event)), this.pointerList.length) {
case 0:
this.eventsSource = _constant.SOURCE_ANY;
break;
case 1:
event.preventDefault(), this.decideMoveOrSwipe(this.pointerList[0]);
break;
case 2:
event.preventDefault(), this.handlePinchStart(this.pointerList);
}
}
}, {
key: "handleEnd",
value: function(event) {
switch (this.currentAction) {
case _constant.ACTION_MOVE:
this.handleMoveEnd(event);
break;
case _constant.ACTION_SWIPE:
this.handleSwipeEnd(event);
break;
case _constant.ACTION_PINCH:
this.handlePinchEnd(event);
}
}
}, {
key: "handleMoveStart",
value: function(_ref3) {
var clientX = _ref3.x, clientY = _ref3.y;
this.props.enableZoom && (this.currentAction = _constant.ACTION_MOVE, this.moveStartX = clientX,
this.moveStartY = clientY, this.moveStartOffsetX = this.state.offsetX, this.moveStartOffsetY = this.state.offsetY);
}
}, {
key: "handleMove",
value: function(_ref4) {
var clientX = _ref4.x, clientY = _ref4.y, newOffsetX = this.moveStartX - clientX + this.moveStartOffsetX, newOffsetY = this.moveStartY - clientY + this.moveStartOffsetY;
this.state.offsetX === newOffsetX && this.state.offsetY === newOffsetY || this.setState({
offsetX: newOffsetX,
offsetY: newOffsetY
});
}
}, {
key: "handleMoveEnd",
value: function() {
var _this9 = this;
this.currentAction = _constant.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(), nextOffsetX = Math.max(maxOffsets.minX, Math.min(maxOffsets.maxX, this.state.offsetX)), nextOffsetY = Math.max(maxOffsets.minY, Math.min(maxOffsets.maxY, this.state.offsetY));
nextOffsetX === this.state.offsetX && nextOffsetY === this.state.offsetY || (this.setState({
offsetX: nextOffsetX,
offsetY: nextOffsetY,
shouldAnimate: !0
}), this.setTimeout(function() {
_this9.setState({
shouldAnimate: !1
});
}, this.props.animationDuration));
}
}, {
key: "handleSwipeStart",
value: function(_ref5) {
var clientX = _ref5.x, clientY = _ref5.y;
this.currentAction = _constant.ACTION_SWIPE, this.swipeStartX = clientX, this.swipeStartY = clientY,
this.swipeEndX = clientX, this.swipeEndY = clientY;
}
}, {
key: "handleSwipe",
value: function(_ref6) {
var clientX = _ref6.x, clientY = _ref6.y;
this.swipeEndX = clientX, this.swipeEndY = clientY;
}
}, {
key: "handleSwipeEnd",
value: function(event) {
var xDiff = this.swipeEndX - this.swipeStartX, xDiffAbs = Math.abs(xDiff), yDiffAbs = Math.abs(this.swipeEndY - this.swipeStartY);
if (this.currentAction = _constant.ACTION_NONE, this.swipeStartX = 0, this.swipeStartY = 0,
this.swipeEndX = 0, this.swipeEndY = 0, !(!event || this.isAnimating() || xDiffAbs < 1.5 * yDiffAbs)) {
if (xDiffAbs < _constant.MIN_SWIPE_DISTANCE) {
var boxRect = this.getLightboxRect();
if (xDiffAbs < boxRect.width / 4) return;
}
xDiff > 0 && this.props.prevSrc ? (event.preventDefault(), this.requestMovePrev()) : xDiff < 0 && this.props.nextSrc && (event.preventDefault(),
this.requestMoveNext());
}
}
}, {
key: "calculatePinchDistance",
value: function() {
var _ref7 = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : this.pinchTouchList, _ref8 = _slicedToArray(_ref7, 2), a = _ref8[0], b = _ref8[1];
return Math.sqrt(Math.po