@geezee/react-ui
Version:
Modern and minimalist React UI library.
127 lines (113 loc) • 4.55 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _JSXStyle from "styled-jsx/style";
import React, { useEffect, useRef, useState } from 'react';
import useTheme from '../styles/use-theme';
import ImageSkeleton from './image.skeleton';
import useRealShape from '../utils/use-real-shape';
import useCurrentState from '../utils/use-current-state';
import useResize from '../utils/use-resize';
var defaultProps = {
disableSkeleton: false,
disableAutoResize: false,
className: '',
scale: '100%',
maxDelay: 3000
};
var Image = function Image(_ref) {
var src = _ref.src,
width = _ref.width,
height = _ref.height,
disableSkeleton = _ref.disableSkeleton,
className = _ref.className,
scale = _ref.scale,
maxDelay = _ref.maxDelay,
disableAutoResize = _ref.disableAutoResize,
props = _objectWithoutProperties(_ref, ["src", "width", "height", "disableSkeleton", "className", "scale", "maxDelay", "disableAutoResize"]);
var showAnimation = !disableSkeleton && width && height;
var w = width ? "".concat(width, "px") : 'auto';
var h = height ? "".concat(height, "px") : 'auto';
var theme = useTheme();
var _useState = useState(true),
_useState2 = _slicedToArray(_useState, 2),
loading = _useState2[0],
setLoading = _useState2[1];
var _useState3 = useState(true),
_useState4 = _slicedToArray(_useState3, 2),
showSkeleton = _useState4[0],
setShowSkeleton = _useState4[1];
var _useCurrentState = useCurrentState(h),
_useCurrentState2 = _slicedToArray(_useCurrentState, 3),
zoomHeight = _useCurrentState2[0],
setZoomHeight = _useCurrentState2[1],
zoomHeightRef = _useCurrentState2[2];
var imageRef = useRef(null);
var _useRealShape = useRealShape(imageRef),
_useRealShape2 = _slicedToArray(_useRealShape, 2),
shape = _useRealShape2[0],
updateShape = _useRealShape2[1];
var imageLoaded = function imageLoaded() {
if (!showAnimation) return;
setLoading(false);
};
useEffect(function () {
if (!showAnimation) return;
if (!imageRef.current) return;
if (imageRef.current.complete) {
setLoading(false);
setShowSkeleton(false);
}
});
useEffect(function () {
var timer = setTimeout(function () {
if (showAnimation) {
setShowSkeleton(false);
}
clearTimeout(timer);
}, maxDelay);
return function () {
return clearTimeout(timer);
};
}, [loading]);
/**
* On mobile devices, the render witdth may be less than CSS width value.
* If the image is scaled, set the height manually.
* This is to ensure the aspect ratio of the image.
*
* If the image is auto width, ignore all.
*/
useEffect(function () {
if (disableAutoResize) return;
var notLoaded = shape.width === 0;
var isAutoZoom = zoomHeightRef.current === 'auto';
if (notLoaded || !width || !height) return;
if (shape.width < width) {
!isAutoZoom && setZoomHeight('auto');
} else {
isAutoZoom && setZoomHeight(h);
}
}, [shape, width]);
useResize(function () {
if (disableAutoResize) return;
updateShape();
});
return /*#__PURE__*/React.createElement("div", {
className: _JSXStyle.dynamic([["286606564", [w, zoomHeight, theme.expressiveness.R2, scale, scale]]]) + " " + "image ".concat(className)
}, showSkeleton && showAnimation && /*#__PURE__*/React.createElement(ImageSkeleton, {
opacity: loading ? 0.5 : 0
}), /*#__PURE__*/React.createElement("img", _extends({
ref: imageRef,
width: width,
height: height,
onLoad: imageLoaded,
src: src
}, props, {
className: _JSXStyle.dynamic([["286606564", [w, zoomHeight, theme.expressiveness.R2, scale, scale]]]) + " " + (props && props.className != null && props.className || "")
})), /*#__PURE__*/React.createElement(_JSXStyle, {
id: "286606564",
dynamic: [w, zoomHeight, theme.expressiveness.R2, scale, scale]
}, ".image.__jsx-style-dynamic-selector{width:".concat(w, ";height:").concat(zoomHeight, ";margin:0 auto;position:relative;border-radius:").concat(theme.expressiveness.R2, ";overflow:hidden;max-width:100%;}img.__jsx-style-dynamic-selector{width:").concat(scale, ";height:").concat(scale, ";object-fit:scale-down;display:block;}")));
};
Image.defaultProps = defaultProps;
export default React.memo(Image);