chayns-components
Version:
A set of beautiful React components for developing chayns® applications.
190 lines (189 loc) • 6.3 kB
JavaScript
/* 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