UNPKG

wix-style-react

Version:
492 lines (424 loc) 20.3 kB
import _extends from "@babel/runtime/helpers/extends"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized"; import _inherits from "@babel/runtime/helpers/inherits"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Delete from 'wix-ui-icons-common/Delete'; import Replace from 'wix-ui-icons-common/Replace'; import Download from 'wix-ui-icons-common/Download'; import More from 'wix-ui-icons-common/More'; import StatusIndicator from '../StatusIndicator'; import Loader from '../Loader'; import { st, classes } from './ImageViewer.st.css'; import Tooltip from '../Tooltip'; import IconButton from '../IconButton'; import AddItem from '../AddItem/AddItem'; import Box from '../Box'; import PopoverMenu from '../PopoverMenu'; import classnames from 'classnames'; import { dataHooks } from './constants'; import { TooltipCommonProps } from '../common/PropTypes/TooltipCommon'; var ImageViewer = /*#__PURE__*/function (_Component) { _inherits(ImageViewer, _Component); var _super = _createSuper(ImageViewer); function ImageViewer(props) { var _this; _classCallCheck(this, ImageViewer); _this = _super.call(this, props); _defineProperty(_assertThisInitialized(_this), "_renderAddImage", function () { var _this$props = _this.props, onAddImage = _this$props.onAddImage, addImageInfo = _this$props.addImageInfo, _this$props$tooltipPr = _this$props.tooltipProps, tooltipProps = _this$props$tooltipPr === void 0 ? {} : _this$props$tooltipPr, disabled = _this$props.disabled; return /*#__PURE__*/React.createElement(AddItem, { ref: _this.focusNode, onClick: onAddImage, theme: "image", dataHook: dataHooks.addItem, disabled: disabled, tooltipProps: _objectSpread(_objectSpread({}, tooltipProps), {}, { content: addImageInfo }) }); }); _defineProperty(_assertThisInitialized(_this), "_renderImageElement", function (_ref) { var imageUrl = _ref.imageUrl, shouldDisplay = _ref.shouldDisplay, onLoad = _ref.onLoad, onError = _ref.onError, key = _ref.key, dataHook = _ref.dataHook; var dataAttributes = { 'data-hook': dataHook, 'data-image-visible': shouldDisplay }; return /*#__PURE__*/React.createElement("img", _extends({ className: classnames([classes.image, classes.stretch, shouldDisplay && classes.imageVisible]), src: imageUrl, onLoad: onLoad, onError: onError, key: key }, dataAttributes)); }); _defineProperty(_assertThisInitialized(_this), "_resetImageLoading", function () { _this.setState({ imageLoading: false }); }); _defineProperty(_assertThisInitialized(_this), "_onImageLoad", function (e) { var onImageLoad = _this.props.onImageLoad; _this.setState({ imageLoading: false }, function () { return onImageLoad(e); }); }); _defineProperty(_assertThisInitialized(_this), "_getCurrentAndPreviousImages", function () { var currentImageUrl = _this.props.imageUrl; var previousImageUrl = _this.state.previousImageUrl; return { currentImageUrl: currentImageUrl, previousImageUrl: previousImageUrl }; }); _defineProperty(_assertThisInitialized(_this), "_renderImage", function () { var imageLoading = _this.state.imageLoading; if (!_this.props.imageUrl) { return; } var _this$_getCurrentAndP = _this._getCurrentAndPreviousImages(), currentImageUrl = _this$_getCurrentAndP.currentImageUrl, previousImageUrl = _this$_getCurrentAndP.previousImageUrl; var shouldDisplayContainer = !!(currentImageUrl || previousImageUrl); var generateKey = function generateKey(imageName, imageUrl) { return "".concat(imageName, "-").concat(imageUrl); }; return /*#__PURE__*/React.createElement("div", { className: st(classes.imageContainer, { /** hide container when no image provided, so AddItem behind it can be clickable */ shouldDisplay: shouldDisplayContainer }), "data-container-visible": shouldDisplayContainer, "data-hook": dataHooks.imagesContainer }, _this._renderImageElement({ imageUrl: currentImageUrl, shouldDisplay: !!currentImageUrl && !imageLoading, onLoad: _this._onImageLoad, onError: function onError() { _this._resetImageLoading(); }, dataHook: dataHooks.image, key: generateKey(dataHooks.image, currentImageUrl) }), _this._renderImageElement({ imageUrl: previousImageUrl, shouldDisplay: imageLoading && !!previousImageUrl, dataHook: dataHooks.previousImage, key: generateKey(dataHooks.previousImage, previousImageUrl) })); }); _defineProperty(_assertThisInitialized(_this), "_renderUpdateButton", function (ref) { var _this$props2 = _this.props, updateImageInfo = _this$props2.updateImageInfo, onUpdateImage = _this$props2.onUpdateImage, tooltipProps = _this$props2.tooltipProps; return /*#__PURE__*/React.createElement(Tooltip, _extends({}, tooltipProps, { timeout: 0, dataHook: dataHooks.updateTooltip, content: updateImageInfo }), /*#__PURE__*/React.createElement(IconButton, { ref: ref, dataHook: dataHooks.update, onClick: onUpdateImage, skin: "light", priority: "secondary" }, /*#__PURE__*/React.createElement(Replace, null))); }); _defineProperty(_assertThisInitialized(_this), "_resetPreviousImage", function () { return _this.setState({ previousImageUrl: undefined }); }); _defineProperty(_assertThisInitialized(_this), "_renderRemoveButton", function (ref) { var _this$props3 = _this.props, removeImageInfo = _this$props3.removeImageInfo, onRemoveImage = _this$props3.onRemoveImage, tooltipProps = _this$props3.tooltipProps; return /*#__PURE__*/React.createElement(Tooltip, _extends({}, tooltipProps, { timeout: 0, dataHook: dataHooks.removeTooltip, content: removeImageInfo }), /*#__PURE__*/React.createElement(IconButton, { ref: ref, dataHook: dataHooks.remove, skin: "light", priority: "secondary", onClick: function onClick(e) { _this._resetPreviousImage(); onRemoveImage && onRemoveImage(e); } }, /*#__PURE__*/React.createElement(Delete, null))); }); _defineProperty(_assertThisInitialized(_this), "_renderDownloadButton", function (ref) { var _this$props4 = _this.props, downloadImageInfo = _this$props4.downloadImageInfo, onDownloadImage = _this$props4.onDownloadImage, tooltipProps = _this$props4.tooltipProps; return /*#__PURE__*/React.createElement(Tooltip, _extends({}, tooltipProps, { timeout: 0, dataHook: dataHooks.downloadTooltip, content: downloadImageInfo }), /*#__PURE__*/React.createElement(IconButton, { ref: ref, dataHook: dataHooks.download, skin: "light", priority: "secondary", onClick: function onClick(e) { onDownloadImage && onDownloadImage(e); } }, /*#__PURE__*/React.createElement(Download, null))); }); _defineProperty(_assertThisInitialized(_this), "_hidePopover", function () { return _this.setState({ popoverOpen: false }); }); _defineProperty(_assertThisInitialized(_this), "_showPopover", function () { return _this.setState({ popoverOpen: true }); }); _defineProperty(_assertThisInitialized(_this), "_renderMoreButton", function () { var _this$props5 = _this.props, tooltipProps = _this$props5.tooltipProps, moreImageInfo = _this$props5.moreImageInfo, downloadImageInfo = _this$props5.downloadImageInfo, onDownloadImage = _this$props5.onDownloadImage, removeImageInfo = _this$props5.removeImageInfo, onRemoveImage = _this$props5.onRemoveImage; return /*#__PURE__*/React.createElement(PopoverMenu, { dataHook: dataHooks.actionsMenu, onHide: _this._hidePopover, onShow: _this._showPopover, triggerElement: function triggerElement(_ref2) { var toggle = _ref2.toggle; return /*#__PURE__*/React.createElement(Tooltip, _extends({}, tooltipProps, { timeout: 0, dataHook: dataHooks.moreTooltip, content: moreImageInfo }), /*#__PURE__*/React.createElement(IconButton, { onClick: toggle, dataHook: dataHooks.more, skin: "light", priority: _this.state.popoverOpen ? 'primary' : 'secondary' }, /*#__PURE__*/React.createElement(More, null))); } }, /*#__PURE__*/React.createElement(PopoverMenu.MenuItem, { prefixIcon: /*#__PURE__*/React.createElement(Download, null), text: downloadImageInfo, onClick: onDownloadImage }), /*#__PURE__*/React.createElement(PopoverMenu.MenuItem, { prefixIcon: /*#__PURE__*/React.createElement(Delete, null), text: removeImageInfo, onClick: onRemoveImage })); }); _defineProperty(_assertThisInitialized(_this), "_renderFirstButton", function () { var _this$props6 = _this.props, showUpdateButton = _this$props6.showUpdateButton, showRemoveButton = _this$props6.showRemoveButton, showDownloadButton = _this$props6.showDownloadButton; if (showUpdateButton) return _this._renderUpdateButton(_this.focusNode); if (showDownloadButton) return _this._renderDownloadButton(_this.focusNode); if (showRemoveButton) return _this._renderRemoveButton(_this.focusNode); return null; }); _defineProperty(_assertThisInitialized(_this), "_renderSecondButton", function () { var _this$props7 = _this.props, showUpdateButton = _this$props7.showUpdateButton, showRemoveButton = _this$props7.showRemoveButton, showDownloadButton = _this$props7.showDownloadButton; // All three options - show more button if (showUpdateButton && showDownloadButton && showRemoveButton) { return _this._renderMoreButton(); } // Two options - show second button if (showUpdateButton && showRemoveButton) return _this._renderRemoveButton(); if (showUpdateButton && showDownloadButton) return _this._renderDownloadButton(); if (showDownloadButton && showRemoveButton) return _this._renderRemoveButton(); return null; }); _defineProperty(_assertThisInitialized(_this), "_renderLoader", function () { return /*#__PURE__*/React.createElement(Box, { align: "center", verticalAlign: "middle", height: "100%", dataHook: dataHooks.loader }, /*#__PURE__*/React.createElement(Loader, { size: "small" })); }); _defineProperty(_assertThisInitialized(_this), "_renderButtons", function () { return /*#__PURE__*/React.createElement("div", { className: classes.buttons }, _this._renderFirstButton(), _this._renderSecondButton()); }); _defineProperty(_assertThisInitialized(_this), "_renderOverlayWith", function (content) { var removeRoundedBorders = _this.props.removeRoundedBorders; var _this$_getCurrentAndP2 = _this._getCurrentAndPreviousImages(), currentImageUrl = _this$_getCurrentAndP2.currentImageUrl, previousImageUrl = _this$_getCurrentAndP2.previousImageUrl; var shouldDisplayOverlay = !!(currentImageUrl || previousImageUrl); return /*#__PURE__*/React.createElement("div", { className: st(classes.overlay, { removeRadius: removeRoundedBorders, shouldDisplay: shouldDisplayOverlay }), "data-remove-radius": removeRoundedBorders, "data-hook": dataHooks.overlay }, content, /*#__PURE__*/React.createElement("span", null)); }); _defineProperty(_assertThisInitialized(_this), "focus", function () { _this.focusNode.current && _this.focusNode.current.focus(); }); var _imageUrl = props.imageUrl; _this.focusNode = /*#__PURE__*/React.createRef(); _this.state = { imageLoading: !!_imageUrl, previousImageUrl: undefined, popoverOpen: false }; return _this; } _createClass(ImageViewer, [{ key: "UNSAFE_componentWillReceiveProps", value: function UNSAFE_componentWillReceiveProps(nextProps) { var currentImageUrl = this.props.imageUrl; var nextImageUrl = nextProps.imageUrl; if (nextImageUrl && currentImageUrl !== nextImageUrl) { this.setState({ imageLoading: true, previousImageUrl: currentImageUrl }); } } }, { key: "render", value: function render() { var _this$props8 = this.props, width = _this$props8.width, height = _this$props8.height, disabled = _this$props8.disabled, dataHook = _this$props8.dataHook, removeRoundedBorders = _this$props8.removeRoundedBorders, imageUrl = _this$props8.imageUrl, status = _this$props8.status, statusMessage = _this$props8.statusMessage, className = _this$props8.className; var _this$state = this.state, imageLoading = _this$state.imageLoading, previousImageUrl = _this$state.previousImageUrl, popoverOpen = _this$state.popoverOpen; var hasImage = !!imageUrl; var hasNoPreviousImageWhileLoading = imageLoading && !previousImageUrl; var imageLoaded = hasImage && !imageLoading; var cssStates = { disabled: disabled, status: !disabled && status, removeRadius: removeRoundedBorders, hasImage: hasImage, popoverOpen: popoverOpen }; var rootDataAttributes = { 'data-disabled': disabled, 'data-image-loaded': imageLoaded, 'data-hook': dataHook }; return /*#__PURE__*/React.createElement("div", _extends({ className: st(classes.root, cssStates, className), style: { width: width, height: height } }, rootDataAttributes), (hasNoPreviousImageWhileLoading || !hasImage) && this._renderAddImage(), this._renderImage(), this._renderOverlayWith(imageLoading ? this._renderLoader() : hasImage && this._renderButtons()), status && !disabled && /*#__PURE__*/React.createElement("div", { className: classes.statusContainer }, /*#__PURE__*/React.createElement(StatusIndicator, { status: status, message: statusMessage, dataHook: dataHooks.errorTooltip }))); } }]); return ImageViewer; }(Component); ImageViewer.displayName = 'ImageViewer'; ImageViewer.defaultProps = { showUpdateButton: true, showDownloadButton: false, showRemoveButton: true, addImageInfo: 'Add Image', updateImageInfo: 'Update', downloadImageInfo: 'Download', removeImageInfo: 'Remove', moreImageInfo: 'More actions', onImageLoad: function onImageLoad() { return {}; } }; ImageViewer.propTypes = { /** Applies a data-hook HTML attribute that can be used in the tests. */ dataHook: PropTypes.string, /** Specifies a CSS class name to be appended to the component’s root element. */ className: PropTypes.string, /** Links to image asset source (URL). Leave it blank when image is not uploaded yet. */ imageUrl: PropTypes.string, /** Specifies the status of a viewer. */ status: PropTypes.oneOf(['error', 'warning', 'loading']), /** Defines the message to display on status icon hover. If not given or empty there will be no tooltip. */ statusMessage: PropTypes.node, /** Allows to pass all common tooltip props. Check `<Tooltip/>` for a full API. */ tooltipProps: PropTypes.shape(TooltipCommonProps), /** Specifies whether the update button is visible. */ showUpdateButton: PropTypes.bool, /** Specifies whether the download button is visible. */ showDownloadButton: PropTypes.bool, /** Specifies whether the remove button is visible. */ showRemoveButton: PropTypes.bool, /** Defines a click handler, which is called every time a user clicks on an empty viewer (when no `imageUrl` is provided). */ onAddImage: PropTypes.func, /** Defines a handler function, which is called every time user clicks on the ‘Update image’ button. */ onUpdateImage: PropTypes.func, /** Defines a handler function, which is called every time user clicks on the download button. */ onDownloadImage: PropTypes.func, /** Defines a handler function, which is called every time user clicks on the ‘Remove image’ button. */ onRemoveImage: PropTypes.func, /** Defines a handler function which is called right after image loads. */ onImageLoad: PropTypes.func, /** Specifies a message to display in a tooltip when no image is uploaded yet. */ addImageInfo: PropTypes.string, /** Defines a message to display in a tooltip when ‘Update’ action button is hovered. */ updateImageInfo: PropTypes.string, /** Defines a message to display in a tooltip when ‘Download’ action button is hovered. */ downloadImageInfo: PropTypes.string, /** Defines a message to display in a tooltip, when ‘remove’ action button is hovered. */ removeImageInfo: PropTypes.string, /** Defines a message to display in a tooltip when the ‘More’ action button is hovered. Relevant only when all buttons are visible. */ moreImageInfo: PropTypes.string, /** Removes default border radius. */ removeRoundedBorders: PropTypes.bool, /** Sets the width of the viewer box. */ width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), /** Sets the height of the viewer box. */ height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), /** Specifies whether the component is disabled. */ disabled: PropTypes.bool }; export default ImageViewer;