UNPKG

chayns-components

Version:

A set of beautiful React components for developing chayns® applications.

190 lines (189 loc) 6.3 kB
/* eslint-disable jsx-a11y/click-events-have-key-events,no-return-assign,react/forbid-prop-types */ import classNames from 'clsx'; import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; import SmallWaitCursor from '../../react-chayns-smallwaitcursor/component/SmallWaitCursor'; import { isString } from '../../utils/is'; import { isServer } from '../../utils/isServer'; import { getDataUrlFromBase64, getDataUrlFromFile } from '../utils/getDataUrl'; import { getImageMetaDataFromApi, getImageMetaDataFromPreview } from '../utils/getImageMetaData'; import "./Image.css"; export default class Image extends PureComponent { constructor(props) { super(props); this.getElementDimensions = () => { this.setState({ elementDimensions: { height: Math.ceil(this.imageRef.current.clientHeight / 50) * 50, width: Math.ceil(this.imageRef.current.clientWidth / 50) * 50 } }); }; this.init = async () => { // set url and metadata this.getElementDimensions(); const { image, styleLandscape, stylePortrait } = this.props; if (isString(image)) { // url if (Image.imageMetaData[image]) { // use cached metadata this.setState({ metaData: Image.imageMetaData[image], imageUrl: image }); } else if (image.indexOf('tsimg.cloud') >= 0) { // get preview and dimensions from tsimg.cloud const metaData = await getImageMetaDataFromApi(image); Image.imageMetaData[image] = metaData; this.setState({ metaData, imageUrl: image }); } else if (styleLandscape || stylePortrait) { // get dimensions if needed const metaData = await getImageMetaDataFromPreview(image); Image.imageMetaData[image] = metaData; this.setState({ metaData, imageUrl: image }); } else { // set only the image url this.setState({ imageUrl: image }); } } else { // file const cacheId = `##FILE##${image.name}${image.lastModified}${image.size}`; if (Image.imageMetaData[cacheId]) { // use cache this.setState(Image.imageMetaData[cacheId]); } else { // get dataUrl, metaData and exifData and set cache const imageUrl = await getDataUrlFromFile(image); const newImage = { imageUrl }; if (styleLandscape || stylePortrait) { // get dimensions if needed newImage.metaData = await getImageMetaDataFromPreview(imageUrl); } Image.imageMetaData[cacheId] = newImage; this.setState(newImage); } } }; this.onReady = () => { this.setState({ ready: true }); }; this.state = { ready: false, imageUrl: null, metaData: null, elementDimensions: null }; this.imageRef = /*#__PURE__*/React.createRef(); } componentDidMount() { this.init(); } componentDidUpdate(prevProps) { if (prevProps !== this.props) { this.init(); } } render() { const { moreImages, onClick, className, classNameLandscape, classNamePortrait, style, styleLandscape, stylePortrait, preventParams } = this.props; const { metaData, imageUrl, ready, elementDimensions } = this.state; let format = 0; if (metaData) { format = metaData.width > metaData.height ? Image.format.LANDSCAPE : Image.format.PORTRAIT; } return /*#__PURE__*/React.createElement("div", { className: classNames('cc__image', className, format === Image.format.LANDSCAPE && ['cc__image--landscape', classNameLandscape], format === Image.format.PORTRAIT && ['cc__image--portrait', classNamePortrait], moreImages > 0 && 'cc__image--more-images', ready && 'cc__image--ready'), ref: this.imageRef, style: { ...style, ...(format === Image.format.LANDSCAPE ? styleLandscape : null), ...(format === Image.format.PORTRAIT ? stylePortrait : null) }, "data-more": moreImages > 0 ? `+${moreImages}` : undefined }, imageUrl ? /*#__PURE__*/React.createElement("img", { onClick: onClick, key: "image", alt: "", src: preventParams === true ? imageUrl : chayns.utils.getScaledImageUrl(imageUrl, !preventParams.height && elementDimensions.height, !preventParams.width && elementDimensions.width, preventParams.format), className: 'cc__image__img' + (onClick ? " cc__image--clickable" : ""), onLoad: this.onReady }) : null, !ready && metaData && metaData.preview ? [/*#__PURE__*/React.createElement("img", { onClick: onClick, key: "preview", alt: "", src: getDataUrlFromBase64(metaData.preview), className: 'cc__image__preview' + (onClick ? " cc__image--clickable" : "") }), /*#__PURE__*/React.createElement("div", { className: "cc__image__wait-cursor", key: "waitCursor" }, /*#__PURE__*/React.createElement(SmallWaitCursor, { show: !ready, showBackground: false }))] : null); } } Image.format = { LANDSCAPE: 1, PORTRAIT: 2 }; Image.imageMetaData = {}; Image.propTypes = { // eslint-disable-next-line react/require-default-props image: isServer() ? PropTypes.any.isRequired : PropTypes.oneOfType([PropTypes.instanceOf(File), PropTypes.string]).isRequired, onClick: PropTypes.func, moreImages: PropTypes.number, className: PropTypes.string, classNameLandscape: PropTypes.string, classNamePortrait: PropTypes.string, style: PropTypes.object, stylePortrait: PropTypes.object, styleLandscape: PropTypes.object, preventParams: PropTypes.oneOfType([PropTypes.bool, PropTypes.shape({ width: PropTypes.bool, height: PropTypes.bool, format: PropTypes.bool })]) }; Image.defaultProps = { moreImages: 0, onClick: null, className: '', classNameLandscape: '', classNamePortrait: '', style: {}, stylePortrait: {}, styleLandscape: {}, preventParams: {} }; Image.displayName = 'Image'; //# sourceMappingURL=Image.js.map