UNPKG

lightbox-react

Version:

Lightbox for React components or images

872 lines (857 loc) 92.7 kB
!function(root, factory) { "object" == typeof exports && "object" == typeof module ? module.exports = factory() : "function" == typeof define && define.amd ? define([], factory) : "object" == typeof exports ? exports.ReactImageLightbox = factory() : root.ReactImageLightbox = factory(); }("undefined" != typeof self ? self : this, function() { /******/ return function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // 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] = { /******/ i: moduleId, /******/ l: !1, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ /******/ /******/ // Return the exports of the module /******/ return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), /******/ /******/ // Flag the module as loaded /******/ module.l = !0, module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__.m = modules, /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules, /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ __webpack_require__.o(exports, name) || /******/ Object.defineProperty(exports, name, { enumerable: !0, get: getter }) /******/; }, /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ "undefined" != typeof Symbol && Symbol.toStringTag && /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }) /******/ , Object.defineProperty(exports, "__esModule", { value: !0 }); }, /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if ( /******/ 1 & mode && (value = __webpack_require__(value)), 8 & mode) return value; /******/ if (4 & mode && "object" == typeof value && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ /******/ if (__webpack_require__.r(ns), /******/ Object.defineProperty(ns, "default", { enumerable: !0, value: value }), 2 & mode && "string" != typeof value) for (var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }, /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function() { return module.default; } : /******/ function() { return module; }; /******/ /******/ return __webpack_require__.d(getter, "a", getter), getter; /******/ }, /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }, /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "", __webpack_require__(__webpack_require__.s = 1); /******/ } /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports) { var g; // This works in non-strict mode g = function() { return this; }(); try { // This works if eval is allowed (see CSP) g = g || new Function("return this")(); } catch (e) { // This works if the window reference is available "object" == typeof window && (g = window); } // g can still be undefined, but nothing to do about it... // We return undefined, instead of nothing here, so it's // easier to handle this case. if(!global) { ...} module.exports = g; }, /* 1 */ /***/ function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }); var obj, _lightboxReact = __webpack_require__(2), _lightboxReact2 = (obj = _lightboxReact) && obj.__esModule ? obj : { default: obj }; exports.default = _lightboxReact2.default; }, /* 2 */ /***/ function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */ /* WEBPACK VAR INJECTION */ (function(global) { Object.defineProperty(exports, "__esModule", { value: !0 }); var _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; }, _slicedToArray = function() { return function(arr, i) { if (Array.isArray(arr)) return arr; if (Symbol.iterator in Object(arr)) return function(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; }(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; }; }(), _react = __webpack_require__(3), _react2 = _interopRequireDefault(_react), _propTypes2 = _interopRequireDefault(__webpack_require__(4)), _reactModal2 = _interopRequireDefault(__webpack_require__(5)), _isReact2 = _interopRequireDefault(__webpack_require__(6)), _util = __webpack_require__(7), _constant = __webpack_require__(8); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } return Array.from(arr); } 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; } __webpack_require__(9); var ReactImageLightbox = function(_Component) { function ReactImageLightbox(props) { !function(instance, Constructor) { if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); }(this, ReactImageLightbox); var _this = function(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; }(this, (ReactImageLightbox.__proto__ || Object.getPrototypeOf(ReactImageLightbox)).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, // image load error for srcType loadErrorStatus: {} }, _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; } return function(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); }(ReactImageLightbox, _react.Component), _createClass(ReactImageLightbox, null, [ { key: "isTargetMatchImage", value: function(target) { return target && /ril-image-current/.test(target.className); } }, { key: "parseMouseEvent", value: function(mouseEvent) { return { id: "mouse", source: _constant.SOURCE_MOUSE, x: parseInt(mouseEvent.clientX, 10), y: parseInt(mouseEvent.clientY, 10) }; } }, { key: "parseTouchPointer", value: function(touchPointer) { return { id: touchPointer.identifier, source: _constant.SOURCE_TOUCH, x: parseInt(touchPointer.clientX, 10), y: parseInt(touchPointer.clientY, 10) }; } }, { key: "parsePointerEvent", value: function(pointerEvent) { return { id: pointerEvent.pointerId, source: _constant.SOURCE_POINTER, x: parseInt(pointerEvent.clientX, 10), y: parseInt(pointerEvent.clientY, 10) }; } // Request to transition to the previous image }, { key: "getTransform", value: function(_ref) { var _ref$x = _ref.x, x = void 0 === _ref$x ? 0 : _ref$x, _ref$y = _ref.y, y = void 0 === _ref$y ? 0 : _ref$y, _ref$zoom = _ref.zoom, zoom = void 0 === _ref$zoom ? 1 : _ref$zoom, width = _ref.width, targetWidth = _ref.targetWidth, nextX = x, windowWidth = (0, _util.getWindowWidth)(); width > windowWidth && (nextX += (windowWidth - width) / 2); var scaleFactor = zoom; return width && targetWidth && (scaleFactor = zoom * (targetWidth / width)), { transform: "translate3d(" + nextX + "px," + y + "px,0) scale3d(" + scaleFactor + "," + scaleFactor + ",1)" }; } } ]), _createClass(ReactImageLightbox, [ { 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, // 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() { var _this2 = this; // Prevents cross-origin errors when using a cross-origin iframe this.windowContext = (0, _util.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]); }), this.loadAllImages(); } }, { key: "componentWillReceiveProps", value: function(nextProps) { var _this3 = this, sourcesChanged = !1, prevSrcDict = {}, nextSrcDict = {}; // Iterate through the source types for prevProps and nextProps to // determine if any of the sources changed this.getSrcTypes().forEach(function(srcType) { _this3.props[srcType.name] !== nextProps[srcType.name] && (sourcesChanged = !0, prevSrcDict[_this3.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 _this3.imageCache && (_this3.imageCache[prevSrc].loaded = !1); }), this.moveRequested = !1, // Load any new images this.loadAllImages(nextProps)); } }, { key: "shouldComponentUpdate", value: function() { // Wait for move... return !this.moveRequested; } }, { key: "componentWillUnmount", value: function() { var _this4 = this; this.didUnmount = !0, Object.keys(this.listeners).forEach(function(type) { _this4.windowContext.removeEventListener(type, _this4.listeners[type]); }), 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 _this5 = this, id = setTimeout(function() { _this5.timeouts = _this5.timeouts.filter(function(tid) { return tid !== id; }), func(); }, time); return this.timeouts.push(id), id; }) }, { key: "setPreventInnerClose", value: function() { var _this6 = this; this.preventInnerCloseTimeout && this.clearTimeout(this.preventInnerCloseTimeout), this.preventInnerClose = !0, this.preventInnerCloseTimeout = this.setTimeout(function() { _this6.preventInnerClose = !1, _this6.preventInnerCloseTimeout = null; }, 100); } // Get info for the best suited image to display with the given srcType }, { 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"])) return null; // 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); } 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(width, height, stretch) { var boxSize = this.getLightboxRect(), maxHeight = boxSize.height - 2 * this.props.imagePadding, maxWidth = boxSize.width - 2 * this.props.imagePadding; return stretch || (maxHeight = Math.min(maxHeight, height), maxWidth = Math.min(maxWidth, width)), maxWidth / maxHeight > width / height ? { 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, maxY = 0; return { maxX: // 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, maxY: // if there is still blank space in the Y dimension, don't limit except to the opposite edge maxY = zoomMultiplier * currentImageInfo.height - boxSize.height < 0 ? (boxSize.height - zoomMultiplier * currentImageInfo.height) / 2 : (zoomMultiplier * currentImageInfo.height - boxSize.height) / 2, minX: -1 * maxX, minY: -1 * maxY }; } // Get image src types }, { 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) } ]; } /** * Get sizing when the image is scaled */ }, { 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); } /** * Get the size of the lightbox in pixels */ }, { 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: "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: "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) { var imageBaseSize = this.getBestImageForType("mainSrc"); if (null !== imageBaseSize) { var currentZoomMultiplier = this.getZoomMultiplier(), nextZoomMultiplier = this.getZoomMultiplier(nextZoomLevel), boxRect = this.getLightboxRect(), pointerX = void 0 !== clientX ? clientX - boxRect.left : boxRect.width / 2, pointerY = void 0 !== clientY ? clientY - boxRect.top : boxRect.height / 2, currentImageOffsetX = (boxRect.width - imageBaseSize.width * currentZoomMultiplier) / 2, currentImageOffsetY = (boxRect.height - imageBaseSize.height * currentZoomMultiplier) / 2, nextImageRealOffsetX = pointerX - (pointerX - (currentImageOffsetX - this.state.offsetX)) / currentZoomMultiplier * nextZoomMultiplier, nextImageRealOffsetY = pointerY - (pointerY - (currentImageOffsetY - this.state.offsetY)) / currentZoomMultiplier * nextZoomMultiplier, nextOffsetX = (boxRect.width - imageBaseSize.width * nextZoomMultiplier) / 2 - nextImageRealOffsetX, nextOffsetY = (boxRect.height - imageBaseSize.height * nextZoomMultiplier) / 2 - 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 }); } } else // Snap back to center if zoomed all the way out this.setState({ zoomLevel: nextZoomLevel, offsetX: 0, offsetY: 0 }); } } }, { key: "closeIfClickInner", value: function(event) { !this.preventInnerClose && event.target.className.search(/\bril-inner\b/) > -1 && this.requestClose(event); } /** * Handle user keyboard actions */ }, { key: "handleKeyInput", value: function(event) { // Ignore key input during animations if (event.stopPropagation(), !this.isAnimating()) // Allow slightly faster navigation through the images when user presses keys repeatedly if ("keyup" !== event.type) { var keyCode = event.which || event.keyCode, currentTime = new Date(); // 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 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) 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) return; event.preventDefault(), this.keyPressed = !0, this.requestMoveNext(event); } } else this.lastKeyDownTime -= this.props.keyRepeatKeyupBonus; } /** * Handle a mouse wheel event over the lightbox container */ }, { key: "handleOuterMousewheel", value: function(event) { var _this7 = this; // Prevent scrolling of the background event.preventDefault(), event.stopPropagation(); var xThreshold = _constant.WHEEL_MOVE_X_THRESHOLD, actionDelay = 0; // Prevent rapid-fire zoom behavior if (this.clearTimeout(this.resetScrollTimeout), this.resetScrollTimeout = this.setTimeout(function() { _this7.scrollX = 0, _this7.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 = 500, this.scrollX = 0) : (this.scrollX <= -1 * xThreshold || event.deltaX <= -1 * bigLeapX) && ( // Scroll left moves to previous this.requestMovePrev(event), actionDelay = 500, this.scrollX = 0); } // Allow successive actions after the set delay 0 !== actionDelay && (this.wheelActionTimeout = this.setTimeout(function() { _this7.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); } } /** * Handle a double click on the current image */ }, { 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(_ref2) { return _ref2.id !== pointer.id; }); } }, { key: "filterPointersBySource", value: function() { var _this8 = this; this.pointerList = this.pointerList.filter(function(_ref3) { return _ref3.source === _this8.eventsSource; }); } }, { key: "handleMouseDown", value: function(event) { this.shouldHandleEvent(_constant.SOURCE_MOUSE) && ReactImageLightbox.isTargetMatchImage(event.target) && (this.addPointer(ReactImageLightbox.parseMouseEvent(event)), this.multiPointerStart(event)); } }, { key: "handleMouseMove", value: function(event) { this.shouldHandleEvent(_constant.SOURCE_MOUSE) && this.multiPointerMove(event, [ ReactImageLightbox.parseMouseEvent(event) ]); } }, { key: "handleMouseUp", value: function(event) { this.shouldHandleEvent(_constant.SOURCE_MOUSE) && (this.removePointer(ReactImageLightbox.parseMouseEvent(event)), this.multiPointerEnd(event)); } }, { key: "handlePointerEvent", value: function(event) { if (this.shouldHandleEvent(_constant.SOURCE_POINTER)) switch (event.type) { case "pointerdown": 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); } } }, { key: "handleTouchStart", value: function(event) { var _this9 = this; this.shouldHandleEvent(_constant.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(event) { this.shouldHandleEvent(_constant.SOURCE_TOUCH) && this.multiPointerMove(event, [].map.call(event.changedTouches, function(eventTouch) { return ReactImageLightbox.parseTouchPointer(eventTouch); })); } }, { key: "handleTouchEnd", value: function(event) { var _this10 = this; this.shouldHandleEvent(_constant.SOURCE_TOUCH) && ([].map.call(event.changedTouches, function(touch) { return _this10.removePointer(ReactImageLightbox.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); } } // Handle move start over the lightbox container // This happens: // - On a mouseDown event // - On a touchstart event }, { key: "handleMoveStart", value: function(_ref4) { var clientX = _ref4.x, clientY = _ref4.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); } // 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(_ref5) { var clientX = _ref5.x, clientY = _ref5.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 _this11 = 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() { _this11.setState({ shouldAnimate: !1 }); }, this.props.animationDuration)); }