UNPKG

react-image-magnify

Version:

A responsive image zoom component designed for shopping sites.

363 lines (311 loc) 15 kB
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 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 && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { 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: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } import detectIt from 'detect-it'; import objectAssign from 'object-assign'; import PropTypes from 'prop-types'; import React from 'react'; import ReactCursorPosition from 'react-cursor-position'; import RenderEnlargedImage from './RenderEnlargedImage'; import NegativeSpaceLens from './lens/negative-space'; import PositiveSpaceLens from './lens/positive-space'; import DisplayUntilActive from './hint/DisplayUntilActive'; import Hint from './hint/DefaultHint'; import { getLensCursorOffset } from './lib/lens'; import { getEnlargedImageContainerDimension } from './lib/dimensions'; import { getContainerStyle, getSmallImageStyle } from './lib/styles'; import { LargeImageShape, SmallImageShape } from './prop-types/Image'; import { EnlargedImagePosition, EnlargedImageContainerDimensions } from './prop-types/EnlargedImage'; import { noop } from './utils'; import { INPUT_TYPE, ENLARGED_IMAGE_POSITION } from './constants'; var ReactImageMagnify = function (_React$Component) { _inherits(ReactImageMagnify, _React$Component); function ReactImageMagnify(props) { _classCallCheck(this, ReactImageMagnify); var _this = _possibleConstructorReturn(this, (ReactImageMagnify.__proto__ || Object.getPrototypeOf(ReactImageMagnify)).call(this, props)); var primaryInput = detectIt.primaryInput; var MOUSE = INPUT_TYPE.mouse, TOUCH = INPUT_TYPE.touch; _this.state = { smallImageWidth: 0, smallImageHeight: 0, detectedInputType: { isMouseDeteced: primaryInput === MOUSE, isTouchDetected: primaryInput === TOUCH } }; _this.onSmallImageLoad = _this.onSmallImageLoad.bind(_this); _this.setSmallImageDimensionState = _this.setSmallImageDimensionState.bind(_this); _this.onDetectedInputTypeChanged = _this.onDetectedInputTypeChanged.bind(_this); return _this; } _createClass(ReactImageMagnify, [{ key: 'componentDidMount', value: function componentDidMount() { var isFluidWidth = this.props.smallImage.isFluidWidth; if (!isFluidWidth) { return; } this.setSmallImageDimensionState(); window.addEventListener('resize', this.setSmallImageDimensionState); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { window.removeEventListener('resize', this.setSmallImageDimensionState); } }, { key: 'onSmallImageLoad', value: function onSmallImageLoad(e) { var _props$smallImage = this.props.smallImage, _props$smallImage$onL = _props$smallImage.onLoad, onLoad = _props$smallImage$onL === undefined ? noop : _props$smallImage$onL, isFluidWidth = _props$smallImage.isFluidWidth; onLoad(e); if (!isFluidWidth) { return; } this.setSmallImageDimensionState(); } }, { key: 'onDetectedInputTypeChanged', value: function onDetectedInputTypeChanged(detectedInputType) { this.setState({ detectedInputType: detectedInputType }); } }, { key: 'setSmallImageDimensionState', value: function setSmallImageDimensionState() { var _smallImageEl = this.smallImageEl, smallImageWidth = _smallImageEl.offsetWidth, smallImageHeight = _smallImageEl.offsetHeight; this.setState({ smallImageWidth: smallImageWidth, smallImageHeight: smallImageHeight }); } }, { key: 'render', value: function render() { var _this2 = this; var _props = this.props, className = _props.className, style = _props.style, hoverDelayInMs = _props.hoverDelayInMs, hoverOffDelayInMs = _props.hoverOffDelayInMs, isActivatedOnTouch = _props.isActivatedOnTouch, pressDuration = _props.pressDuration, pressMoveThreshold = _props.pressMoveThreshold, _props$smallImage$onE = _props.smallImage.onError, onError = _props$smallImage$onE === undefined ? noop : _props$smallImage$onE, imageClassName = _props.imageClassName, imageStyle = _props.imageStyle, lensStyle = _props.lensStyle, largeImage = _props.largeImage, enlargedImageContainerClassName = _props.enlargedImageContainerClassName, enlargedImageContainerStyle = _props.enlargedImageContainerStyle, enlargedImageClassName = _props.enlargedImageClassName, enlargedImageStyle = _props.enlargedImageStyle, enlargedImagePortalId = _props.enlargedImagePortalId, isEnlargedImagePortalEnabledForTouch = _props.isEnlargedImagePortalEnabledForTouch, fadeDurationInMs = _props.fadeDurationInMs, HintComponent = _props.hintComponent, isHintEnabled = _props.isHintEnabled, hintTextMouse = _props.hintTextMouse, hintTextTouch = _props.hintTextTouch, shouldHideHintAfterFirstActivation = _props.shouldHideHintAfterFirstActivation; var smallImage = this.smallImage; var isTouchDetected = this.state.detectedInputType.isTouchDetected; var cursorOffset = getLensCursorOffset(smallImage, largeImage, this.enlargedImageContainerDimensions); var Lens = this.lensComponent; return React.createElement( ReactCursorPosition, { className: className, hoverDelayInMs: hoverDelayInMs, hoverOffDelayInMs: hoverOffDelayInMs, isActivatedOnTouch: isActivatedOnTouch, onDetectedInputTypeChanged: this.onDetectedInputTypeChanged, pressDuration: pressDuration, pressMoveThreshold: pressMoveThreshold, shouldStopTouchMovePropagation: true, style: getContainerStyle(smallImage, style) }, React.createElement('img', { src: smallImage.src, srcSet: smallImage.srcSet, sizes: smallImage.sizes, alt: smallImage.alt, className: imageClassName, style: getSmallImageStyle(smallImage, imageStyle), ref: function ref(el) { return _this2.smallImageEl = el; }, onLoad: this.onSmallImageLoad, onError: onError }), isHintEnabled && React.createElement( DisplayUntilActive, { shouldHideAfterFirstActivation: shouldHideHintAfterFirstActivation }, React.createElement(HintComponent, { isTouchDetected: isTouchDetected, hintTextMouse: hintTextMouse, hintTextTouch: hintTextTouch }) ), this.shouldShowLens && React.createElement(Lens, { cursorOffset: cursorOffset, fadeDurationInMs: fadeDurationInMs, smallImage: smallImage, style: lensStyle }), React.createElement(RenderEnlargedImage, { containerClassName: enlargedImageContainerClassName, containerDimensions: this.enlargedImageContainerDimensions, containerStyle: enlargedImageContainerStyle, cursorOffset: cursorOffset, fadeDurationInMs: fadeDurationInMs, imageClassName: enlargedImageClassName, imageStyle: enlargedImageStyle, largeImage: largeImage, smallImage: smallImage, portalId: enlargedImagePortalId, isPortalEnabledForTouch: isEnlargedImagePortalEnabledForTouch, isTouchDetected: this.isTouchDetected, isInPlaceMode: this.isInPlaceMode }) ); } }, { key: 'smallImage', get: function get() { var _props2 = this.props, smallImage = _props2.smallImage, isFluidWidth = _props2.smallImage.isFluidWidth; if (!isFluidWidth) { return smallImage; } var _state = this.state, fluidWidth = _state.smallImageWidth, fluidHeight = _state.smallImageHeight; return objectAssign({}, smallImage, { width: fluidWidth, height: fluidHeight }); } }, { key: 'enlargedImagePlacement', get: function get() { var userDefinedEnlargedImagePosition = this.props.enlargedImagePosition; var isTouchDetected = this.state.detectedInputType.isTouchDetected; var computedEnlargedImagePosition = isTouchDetected ? ENLARGED_IMAGE_POSITION.over : ENLARGED_IMAGE_POSITION.beside; return userDefinedEnlargedImagePosition || computedEnlargedImagePosition; } }, { key: 'isInPlaceMode', get: function get() { var OVER = ENLARGED_IMAGE_POSITION.over; return this.enlargedImagePlacement === OVER; } }, { key: 'enlargedImageContainerDimensions', get: function get() { var _props$enlargedImageC = this.props.enlargedImageContainerDimensions, containerWidth = _props$enlargedImageC.width, containerHeight = _props$enlargedImageC.height; var _smallImage = this.smallImage, smallImageWidth = _smallImage.width, smallImageHeight = _smallImage.height; var isInPlaceMode = this.isInPlaceMode; return { width: getEnlargedImageContainerDimension({ containerDimension: containerWidth, smallImageDimension: smallImageWidth, isInPlaceMode: isInPlaceMode }), height: getEnlargedImageContainerDimension({ containerDimension: containerHeight, smallImageDimension: smallImageHeight, isInPlaceMode: isInPlaceMode }) }; } }, { key: 'isTouchDetected', get: function get() { var isTouchDetected = this.state.detectedInputType.isTouchDetected; return isTouchDetected; } }, { key: 'shouldShowLens', get: function get() { return !this.isInPlaceMode && !this.isTouchDetected; } }, { key: 'lensComponent', get: function get() { var _props3 = this.props, shouldUsePositiveSpaceLens = _props3.shouldUsePositiveSpaceLens, lensComponent = _props3.lensComponent; if (lensComponent) { return lensComponent; } if (shouldUsePositiveSpaceLens) { return PositiveSpaceLens; } return NegativeSpaceLens; } }]); return ReactImageMagnify; }(React.Component); ReactImageMagnify.propTypes = { className: PropTypes.string, style: PropTypes.object, hoverDelayInMs: PropTypes.number, hoverOffDelayInMs: PropTypes.number, fadeDurationInMs: PropTypes.number, pressDuration: PropTypes.number, pressMoveThreshold: PropTypes.number, isActivatedOnTouch: PropTypes.bool, imageClassName: PropTypes.string, imageStyle: PropTypes.object, lensStyle: PropTypes.object, lensComponent: PropTypes.func, shouldUsePositiveSpaceLens: PropTypes.bool, smallImage: SmallImageShape, largeImage: LargeImageShape, enlargedImageContainerClassName: PropTypes.string, enlargedImageContainerStyle: PropTypes.object, enlargedImageClassName: PropTypes.string, enlargedImageStyle: PropTypes.object, enlargedImageContainerDimensions: EnlargedImageContainerDimensions, enlargedImagePosition: EnlargedImagePosition, enlargedImagePortalId: PropTypes.string, isEnlargedImagePortalEnabledForTouch: PropTypes.bool, hintComponent: PropTypes.func, hintTextMouse: PropTypes.string, hintTextTouch: PropTypes.string, isHintEnabled: PropTypes.bool, shouldHideHintAfterFirstActivation: PropTypes.bool }; ReactImageMagnify.defaultProps = { enlargedImageContainerDimensions: { width: '100%', height: '100%' }, isEnlargedImagePortalEnabledForTouch: false, fadeDurationInMs: 300, hintComponent: Hint, shouldHideHintAfterFirstActivation: true, isHintEnabled: false, hintTextMouse: 'Hover to Zoom', hintTextTouch: 'Long-Touch to Zoom', hoverDelayInMs: 250, hoverOffDelayInMs: 150, shouldUsePositiveSpaceLens: false }; export default ReactImageMagnify;