UNPKG

@momentum-ui/react-collaboration

Version:

Cisco Momentum UI Framework for React Collaboration Applications

378 lines 22.6 kB
/** @component lightbox */ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); import React from 'react'; import PropTypes from 'prop-types'; import Modal from 'react-aria-modal'; import { Icon } from '@momentum-ui/react-collaboration'; import ButtonSimple from '../../components/ButtonSimple'; import TooltipNext from '../../components/Tooltip'; import IconNext from '../../components/Icon'; import MomentumThemeProvider from '../../components/ThemeProvider'; import LoadingSpinner from '../../components/LoadingSpinner'; import { THEME_NAMES } from '../../components/ThemeProvider/ThemeProvider.constants'; import { v4 as uuidv4 } from 'uuid'; /** * @deprecated - Components in the legacy folder (/src/legacy) are deprecated. Please use a component from the components folder (/src/components) instead. Legacy components may not follow accessibility standards. **/ var Lightbox = /** @class */ (function (_super) { __extends(Lightbox, _super); function Lightbox(props) { var _this = _super.call(this, props) || this; _this.state = { viewportDimensions: { width: 600, height: 600, }, zoom: 1, }; _this.handleResize = function () { var viewport = _this.viewport; _this.setState({ viewportDimensions: { width: viewport.offsetWidth, height: viewport.offsetHeight, }, }); }; _this.handleKeyDown = function (e) { var _a = _this.props, index = _a.index, pages = _a.pages; var newIndex; switch (e.keyCode) { // Escape case 27: _this.handleClose(); return; // left arrow & up arrow case 37: case 38: newIndex = Math.max(index - 1, 0); break; // right arrow & down arrow case 39: case 40: newIndex = Math.min(index + 1, pages.length - 1); break; // page up & home case 33: case 36: newIndex = 0; break; // page down & end case 34: case 35: newIndex = pages.length - 1; break; // 1 - 9 case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: newIndex = Math.min(e.keyCode - 49, pages.length - 1); break; default: return; } _this.triggerPageChange(newIndex, e, true); }; _this.handleThumbnailClick = function (index) { var onChange = _this.props.onChange; onChange && onChange(index); }; _this.triggerPageChange = function (index, e, needFocus) { var _a = _this.props, onChange = _a.onChange, pages = _a.pages; var target = _this.lightBox && _this.lightBox.querySelector("[data-index=\"".concat(index, "\"]")); if (index >= 0 && index <= pages.length - 1) { onChange && onChange(index); } e.stopPropagation(); target && target.scrollIntoViewIfNeeded && target.scrollIntoViewIfNeeded(); target && needFocus && target.parentElement.focus(); }; _this.stopPropagation = function (e) { e.stopPropagation(); }; _this.setZoom = function (increment) { var newZoom = _this.state.zoom + increment; _this.setState({ zoom: newZoom < 0.25 ? 0.25 : newZoom, }); }; _this.handleDownload = function () { var onDownload = _this.props.onDownload; onDownload && onDownload(); }; _this.handleClose = function () { var onClose = _this.props.onClose; onClose && onClose(); }; _this.nameId = uuidv4(); return _this; } Lightbox.prototype.componentDidMount = function () { window.addEventListener('keydown', this.handleKeyDown, true); window.addEventListener('resize', this.handleResize, true); var viewport = this.viewport; if (viewport && viewport.clientWidth && viewport.clientHeight) { // eslint-disable-next-line react/no-did-mount-set-state this.setState({ viewportDimensions: { width: viewport.clientWidth, height: viewport.clientHeight, }, }); } }; Lightbox.prototype.componentDidUpdate = function (prevProps) { if (prevProps.index !== this.props.index && this.state.zoom > 1 && this.imgWrapper) { var viewportNode = this.viewport; viewportNode.scrollTop = 0; viewportNode.scrollLeft = (this.imgWrapper.offsetWidth - viewportNode.offsetWidth) / 2; } }; Lightbox.prototype.componentWillUnmount = function () { window.removeEventListener('keydown', this.handleKeyDown, true); window.removeEventListener('resize', this.handleResize, true); }; Lightbox.prototype.render = function () { var _this = this; var _a = this.props, pages = _a.pages, index = _a.index, width = _a.width, height = _a.height, tooltips = _a.tooltips, downloading = _a.downloading, info = _a.info, name = _a.name, applicationId = _a.applicationId, imgClassName = _a.imgClassName, isImageRotated = _a.isImageRotated; var _b = this.state, zoom = _b.zoom, viewportDimensions = _b.viewportDimensions; var currentPage = pages[index]; var showColumn = pages.length > 1; var LightThemeStyle = this.props.theme === THEME_NAMES.LIGHT_WEBEX ? { color: 'var(--mds-color-theme-text-primary-normal)' } : {}; var calculateAspectRatioFit = function (srcWidth, srcHeight, maxWidth, maxHeight) { var maxW, maxH; if (isImageRotated) { maxW = maxHeight; maxH = maxWidth; } else { maxW = maxWidth; maxH = maxHeight; } var ratio = Math.min(maxW / srcWidth, maxH / srcHeight, 1); return { width: Math.round(srcWidth * ratio), height: Math.round(srcHeight * ratio), ratio: ratio, }; }; var getThumbnails = function () { var thumbnails = pages.map(function (page, idx) { var key = "".concat(idx, ":").concat(page.thumb); var body; if (page.decrypting) { var scale = width / 150; var scaleY = height / scale; var style = { height: Math.round(scaleY), }; key += ':decrypting'; body = (React.createElement("div", { className: "md-lightbox__thumbnail" + "".concat((!!page.decrypting && " md-lightbox__thumbnail--decrypting") || ''), "data-index": idx, style: style }, React.createElement(Icon, { className: "md-lightbox__thumbnail--icon", name: "secure_28" }))); } else { body = (React.createElement("img", { alt: name, className: "md-lightbox__thumbnail" + "".concat((!!page.decrypting && " md-lightbox__thumbnail--decrypting") || ''), "data-index": idx, draggable: "false", onDragStart: function () { return false; }, src: page.thumb })); } return (React.createElement("div", { className: 'md-lightbox__thumbnail-wrapper' + "".concat((idx === index && " md-lightbox__thumbnail-wrapper--selected") || ''), key: key, onClick: function () { return _this.handleThumbnailClick(idx); }, onKeyPress: function () { return _this.handleThumbnailClick(idx); }, role: "tab", tabIndex: "0", "aria-selected": idx === index ? true : false }, body, React.createElement("div", null, idx + 1))); }); return React.createElement("div", { className: "md-lightbox__list" }, thumbnails); }; var newWidth = width; var newHeight = height; var getViewport = function () { var viewport; var imageContainerStyles; if (currentPage.content) { if (currentPage.fullView) { imageContainerStyles = { width: '100%', height: '100%', overflow: 'hidden', }; } viewport = (React.createElement("div", { className: "md-lightbox__viewport-content", draggable: "false", onClick: _this.stopPropagation, onKeyPress: _this.stopPropagation, onDoubleClick: function () { return _this.setZoom(0.25); }, onDragStart: function () { return false; }, role: "button", tabIndex: "0" }, currentPage.content)); } else if (currentPage.image) { if (zoom <= 1) { var dimensions = calculateAspectRatioFit(width * zoom, height * zoom, viewportDimensions.width, viewportDimensions.height); newHeight = dimensions.height; newWidth = dimensions.width; imageContainerStyles = { width: "".concat(dimensions.width, "px"), height: "".concat(dimensions.height, "px"), }; /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ viewport = (React.createElement("img", { alt: name, className: 'md-lightbox__viewport-image' + "".concat((imgClassName && " ".concat(imgClassName)) || ''), draggable: "false", onClick: _this.stopPropagation, onKeyPress: _this.stopPropagation, onDoubleClick: function () { return _this.setZoom(0.25); }, onDragStart: function () { return false; }, src: currentPage.image })); } else { var dimensions = calculateAspectRatioFit(width, height, viewportDimensions.width, viewportDimensions.height); imageContainerStyles = {}; newHeight = dimensions.height * zoom; newWidth = dimensions.width * zoom; viewport = (React.createElement("img", { alt: name, className: 'md-lightbox__viewport-image' + "".concat((imgClassName && " ".concat(imgClassName)) || ''), draggable: "false", onClick: _this.stopPropagation, onKeyPress: _this.stopPropagation, onDoubleClick: function () { return _this.setZoom(0.25); }, onDragStart: function () { return false; }, src: currentPage.image, style: { maxHeight: newHeight, maxWidth: newWidth, minHeight: newHeight, minWidth: newWidth, } })); } } return (React.createElement("div", { className: "md-lightbox__viewport-wrapper", ref: function (ref) { return (_this.imgWrapper = ref); }, style: imageContainerStyles }, viewport)); }; var leftArrowControl = (React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "right", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__page-control md-lightbox__page-control-icon md-lightbox__page-controls--left", onPress: function (e) { return _this.triggerPageChange(index - 1, e); } }, React.createElement(IconNext, { name: "arrow-left", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 16 })) }, tooltips.previous)); var rightArrowControl = (React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "left", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__page-control md-lightbox__page-control-icon md-lightbox__page-controls--right", onPress: function (e) { return _this.triggerPageChange(index + 1, e); } }, React.createElement(IconNext, { name: "arrow-right", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 16 })) }, tooltips.next)); var viewportControls = function () { var downloadButton = (React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "top", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__control md-lightbox__control-download", onPress: _this.handleDownload }, downloading ? (React.createElement(LoadingSpinner, { "aria-hidden": true })) : (React.createElement(IconNext, { name: "download", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 20, weight: "light" }))) }, downloading ? tooltips.downloading : tooltips.download)); var controlStyle = currentPage.content ? { visibility: 'hidden', } : {}; var pageControl = pages.length > 1 ? (React.createElement("div", { className: "md-lightbox__controls md-lightbox__controls--center" }, React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "top", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__control md-lightbox__control-left", onPress: function (e) { return _this.triggerPageChange(index - 1, e); } }, React.createElement(IconNext, { name: "arrow-left", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 20, weight: "light" })) }, tooltips.previous), React.createElement("span", { className: "md-lightbox__control-value" }, "".concat(index + 1, " / ").concat(pages.length)), React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "top", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__control md-lightbox__control-right", onPress: function (e) { return _this.triggerPageChange(index + 1, e); } }, React.createElement(IconNext, { name: "arrow-right", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 20, weight: "light" })) }, tooltips.next))) : (React.createElement("div", { className: "md-lightbox__controls" }, React.createElement("span", { className: "md-lightbox__control-value" }, index + 1))); return (React.createElement("div", { className: "md-lightbox__viewer-controls", onClick: _this.stopPropagation, onKeyPress: _this.stopPropagation, role: "group" }, React.createElement("div", { className: "md-lightbox__controls", style: controlStyle }, React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "top", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__control", "data-test": "zoom-out-button", onPress: function () { return _this.setZoom(-0.25); } }, React.createElement(IconNext, { name: "zoom-out", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 20, weight: "light" })) }, tooltips.zoomOut), React.createElement("span", { className: "md-lightbox__control-value md-lightbox__control-zoom-level" }, "".concat(Math.round(((newHeight * 1.0) / height) * 100), "%")), React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "top", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__control", "data-test": "zoom-in-button", onPress: function () { return _this.setZoom(0.25); } }, React.createElement(IconNext, { name: "zoom-in", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 20, weight: "light" })) }, tooltips.zoomIn)), pageControl, _this.props.onDownload && downloadButton)); }; return (React.createElement(Modal, { includeDefaultStyles: false, getApplicationNode: function () { return document.querySelector("#".concat(applicationId)); }, onExit: this.handleClose, focusDialog: true, titleId: "md-lightbox", dialogClass: "md-lightbox", underlayClass: "md-lightbox__container", "aria-labelledby": this.nameId }, React.createElement(MomentumThemeProvider, { theme: this.props.theme }, React.createElement("div", { className: "md-lightbox__header" }, React.createElement("div", { className: "md-lightbox__header-item--left" }, React.createElement("div", { className: "md-lightbox__header-meta" }, React.createElement("div", { className: "md-lightbox__header-sharer" }, info.sharedBy), React.createElement("div", { className: "md-lightbox__header-timestamp" }, info.sharedOn))), React.createElement("div", { className: "md-lightbox__header-item--center" }, React.createElement("h2", { className: "md-lightbox__header-name", id: this.nameId }, name)), React.createElement("div", { className: "md-lightbox__header-item--right" }, React.createElement(TooltipNext, { style: LightThemeStyle, type: "label", placement: "bottom-start", triggerComponent: React.createElement(ButtonSimple, { className: "md-lightbox__control md-lightbox__control-close", onPress: this.handleClose }, React.createElement(IconNext, { name: "cancel", fillColor: "var(--mds-color-theme-common-text-primary-normal)", scale: 20, weight: "light" })) }, tooltips.exit))), React.createElement("div", { className: "md-lightbox__body", ref: function (ref) { return (_this.lightBox = ref); }, role: "tablist" }, showColumn && getThumbnails(), React.createElement("div", { className: "md-lightbox__content" }, React.createElement("div", { className: "md-lightbox__viewport" + "".concat((!!currentPage.decrypting && " md-lightbox__viewport--decrypting") || ''), ref: function (ref) { return (_this.viewport = ref); } }, pages[index].decrypting && (React.createElement(LoadingSpinner, { className: "md-lightbox__decrypting-spinner", "aria-hidden": true, scale: 32 })), getViewport()), showColumn && leftArrowControl, showColumn && rightArrowControl, viewportControls()))))); }; return Lightbox; }(React.Component)); Lightbox.propTypes = { /** @prop ID for Lightbox query lookup */ applicationId: PropTypes.string.isRequired, /** Determines if info is decrypting | false */ decrypting: PropTypes.bool, /** @prop Optional downloading css styling | false */ downloading: PropTypes.bool, /** @prop Set Height value of Lightbox */ height: PropTypes.number.isRequired, /** @prop Classname appended to img viewport | '' */ imgClassName: PropTypes.string, /** @prop Initial index of start page | 0 */ index: PropTypes.number, /** @prop Lightbox information Object | {} */ info: PropTypes.shape({ sharedBy: PropTypes.string, sharedOn: PropTypes.string, size: PropTypes.string, }), /** @prop Optional indication if image is rotated | false */ isImageRotated: PropTypes.bool, /** @prop Required name prop for Lightbox */ name: PropTypes.string.isRequired, /** @prop Callback function invoked by user when interact with Lightbox | null */ onChange: PropTypes.func, /** @prop Callback function invoked by user closing the Lightbox | null */ onClose: PropTypes.func, /** @prop Callback function invoked by the download action of Lightbox | null */ onDownload: PropTypes.func, /** @prop Array of Lightbox pages */ pages: PropTypes.array.isRequired, /** @prop tooltip style | {isContained:true, direction: 'bottom-right'} */ popoverProps: PropTypes.object, /** @prop theme -- used to pass down to the ThemeProvider */ theme: PropTypes.string, /** @prop Collection of predefined tootips for various Lightbox actions | { download: 'Download', etc } */ tooltips: PropTypes.shape({ download: PropTypes.string, downloading: PropTypes.string, exit: PropTypes.string, previous: PropTypes.string, next: PropTypes.string, zoomIn: PropTypes.string, zoomOut: PropTypes.string, }), /** @prop Set Width value for Lightbox */ width: PropTypes.number.isRequired, }; Lightbox.defaultProps = { decrypting: false, downloading: false, imgClassName: '', index: 0, info: {}, isImageRotated: false, name: '', onChange: null, onClose: null, onDownload: null, popoverProps: { isContained: true, direction: 'bottom-right', }, theme: 'darkWebex', tooltips: { download: 'Download', downloading: 'Downloading...', exit: 'Exit', previous: 'Previous', next: 'Next', zoomIn: 'Zoom in', zoomOut: 'Zoom out', }, }; Lightbox.displayName = 'Lightbox'; export default Lightbox; //# sourceMappingURL=index.js.map