UNPKG

antd-mobile

Version:
99 lines 3.26 kB
import { mergeProps } from '../../utils/with-default-props'; import React, { useState, useRef, useEffect } from 'react'; import { withNativeProps } from '../../utils/native-props'; import { staged } from 'staged-components'; import { toCSSLength } from '../../utils/to-css-length'; import { LazyDetector } from './lazy-detector'; import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect'; import { ImageIcon } from './image-icon'; import { BrokenImageIcon } from './broken-image-icon'; const classPrefix = `adm-image`; const defaultProps = { fit: 'fill', placeholder: React.createElement("div", { className: `${classPrefix}-tip` }, React.createElement(ImageIcon, null)), fallback: React.createElement("div", { className: `${classPrefix}-tip` }, React.createElement(BrokenImageIcon, null)), lazy: false, draggable: false }; export const Image = staged(p => { const props = mergeProps(defaultProps, p); const [loaded, setLoaded] = useState(false); const [failed, setFailed] = useState(false); const ref = useRef(null); const imgRef = useRef(null); let src = props.src; let srcSet = props.srcSet; const [initialized, setInitialized] = useState(!props.lazy); src = initialized ? props.src : undefined; srcSet = initialized ? props.srcSet : undefined; useIsomorphicUpdateLayoutEffect(() => { setLoaded(false); setFailed(false); }, [src]); useEffect(() => { var _a; // for nextjs ssr if ((_a = imgRef.current) === null || _a === void 0 ? void 0 : _a.complete) { setLoaded(true); } }, []); function renderInner() { if (failed) { return React.createElement(React.Fragment, null, props.fallback); } const img = React.createElement("img", { ref: imgRef, id: props.id, className: `${classPrefix}-img`, src: src, alt: props.alt, onClick: props.onClick, onLoad: e => { var _a; setLoaded(true); (_a = props.onLoad) === null || _a === void 0 ? void 0 : _a.call(props, e); }, onError: e => { var _a; setFailed(true); (_a = props.onError) === null || _a === void 0 ? void 0 : _a.call(props, e); }, style: { objectFit: props.fit, display: loaded ? 'block' : 'none' }, crossOrigin: props.crossOrigin, decoding: props.decoding, loading: props.loading, referrerPolicy: props.referrerPolicy, sizes: props.sizes, srcSet: srcSet, useMap: props.useMap, draggable: props.draggable }); return React.createElement(React.Fragment, null, !loaded && props.placeholder, img); } const style = {}; if (props.width) { style['--width'] = toCSSLength(props.width); style['width'] = toCSSLength(props.width); } if (props.height) { style['--height'] = toCSSLength(props.height); style['height'] = toCSSLength(props.height); } return withNativeProps(props, React.createElement("div", { ref: ref, className: classPrefix, style: style, onClick: props.onContainerClick }, props.lazy && !initialized && React.createElement(LazyDetector, { onActive: () => { setInitialized(true); } }), renderInner())); });