office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
139 lines • 6.92 kB
JavaScript
import * as tslib_1 from "tslib";
import * as React from 'react';
import { BaseComponent, classNamesFunction, getNativeProps, imageProperties, createRef } from '../../Utilities';
import { ImageCoverStyle, ImageFit, ImageLoadState } from './Image.types';
var getClassNames = classNamesFunction();
var KEY_PREFIX = 'fabricImage';
var ImageBase = /** @class */ (function (_super) {
tslib_1.__extends(ImageBase, _super);
function ImageBase(props) {
var _this = _super.call(this, props) || this;
// Make an initial assumption about the image layout until we can
// check the rendered element. The value here only takes effect when
// shouldStartVisible is true.
_this._coverStyle = ImageCoverStyle.portrait;
_this._imageElement = createRef();
_this._frameElement = createRef();
_this._onImageLoaded = function (ev) {
var _a = _this.props, src = _a.src, onLoad = _a.onLoad;
if (onLoad) {
onLoad(ev);
}
_this._computeCoverStyle(_this.props);
if (src) {
_this.setState({
loadState: ImageLoadState.loaded
});
}
};
_this._onImageError = function (ev) {
if (_this.props.onError) {
_this.props.onError(ev);
}
_this.setState({
loadState: ImageLoadState.error
});
};
_this.state = {
loadState: ImageLoadState.notLoaded
};
return _this;
}
ImageBase.prototype.componentWillReceiveProps = function (nextProps) {
if (nextProps.src !== this.props.src) {
this.setState({
loadState: ImageLoadState.notLoaded
});
}
else if (this.state.loadState === ImageLoadState.loaded) {
this._computeCoverStyle(nextProps);
}
};
ImageBase.prototype.componentDidUpdate = function (prevProps, prevState) {
this._checkImageLoaded();
if (this.props.onLoadingStateChange && prevState.loadState !== this.state.loadState) {
this.props.onLoadingStateChange(this.state.loadState);
}
};
ImageBase.prototype.render = function () {
var imageProps = getNativeProps(this.props, imageProperties, ['width', 'height']);
var _a = this.props, src = _a.src, alt = _a.alt, width = _a.width, height = _a.height, shouldFadeIn = _a.shouldFadeIn, shouldStartVisible = _a.shouldStartVisible, className = _a.className, imageFit = _a.imageFit, role = _a.role, maximizeFrame = _a.maximizeFrame, styles = _a.styles, theme = _a.theme;
var loadState = this.state.loadState;
var coverStyle = this.props.coverStyle !== undefined ? this.props.coverStyle : this._coverStyle;
var classNames = getClassNames(styles, {
theme: theme,
className: className,
width: width,
height: height,
maximizeFrame: maximizeFrame,
shouldFadeIn: shouldFadeIn,
shouldStartVisible: shouldStartVisible,
isLoaded: loadState === ImageLoadState.loaded ||
(loadState === ImageLoadState.notLoaded && this.props.shouldStartVisible),
isLandscape: coverStyle === ImageCoverStyle.landscape,
isCenter: imageFit === ImageFit.center,
isContain: imageFit === ImageFit.contain,
isCover: imageFit === ImageFit.cover,
isNone: imageFit === ImageFit.none,
isError: loadState === ImageLoadState.error,
isNotImageFit: imageFit === undefined
});
// If image dimensions aren't specified, the natural size of the image is used.
return (React.createElement("div", { className: classNames.root, style: { width: width, height: height }, ref: this._frameElement },
React.createElement("img", tslib_1.__assign({}, imageProps, { onLoad: this._onImageLoaded, onError: this._onImageError, key: KEY_PREFIX + this.props.src || '', className: classNames.image, ref: this._imageElement, src: src, alt: alt, role: role }))));
};
ImageBase.prototype._checkImageLoaded = function () {
var src = this.props.src;
var loadState = this.state.loadState;
if (loadState === ImageLoadState.notLoaded) {
// testing if naturalWidth and naturalHeight are greater than zero is better than checking
// .complete, because .complete will also be set to true if the image breaks. However,
// for some browsers, SVG images do not have a naturalWidth or naturalHeight, so fall back
// to checking .complete for these images.
var isLoaded = this._imageElement.current
? (src && (this._imageElement.current.naturalWidth > 0 && this._imageElement.current.naturalHeight > 0)) ||
(this._imageElement.current.complete && ImageBase._svgRegex.test(src))
: false;
if (isLoaded) {
this._computeCoverStyle(this.props);
this.setState({
loadState: ImageLoadState.loaded
});
}
}
};
ImageBase.prototype._computeCoverStyle = function (props) {
var imageFit = props.imageFit, width = props.width, height = props.height;
// Do not compute cover style if it was already specified in props
if ((imageFit === ImageFit.cover || imageFit === ImageFit.contain) &&
this.props.coverStyle === undefined &&
this._imageElement.current &&
this._frameElement.current) {
// Determine the desired ratio using the width and height props.
// If those props aren't available, measure measure the frame.
var desiredRatio = void 0;
if (!!width && !!height) {
desiredRatio = width / height;
}
else {
desiredRatio = this._frameElement.current.clientWidth / this._frameElement.current.clientHeight;
}
// Examine the source image to determine its original ratio.
var naturalRatio = this._imageElement.current.naturalWidth / this._imageElement.current.naturalHeight;
// Should we crop from the top or the sides?
if (naturalRatio > desiredRatio) {
this._coverStyle = ImageCoverStyle.landscape;
}
else {
this._coverStyle = ImageCoverStyle.portrait;
}
}
};
ImageBase.defaultProps = {
shouldFadeIn: true
};
ImageBase._svgRegex = /\.svg$/i;
return ImageBase;
}(BaseComponent));
export { ImageBase };
//# sourceMappingURL=Image.base.js.map