/* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/no-static-element-interactions */ import React from "react"; import BaseComponent from "../_base/baseComponent"; import { ImageProps, ImageStates } from "./interface"; import PropTypes from "prop-types"; import { cssClasses } from "@douyinfe/semi-foundation/image/constants"; import cls from "classnames"; import { IconUploadError, IconEyeOpened } from "@douyinfe/semi-icons"; import PreviewInner from "./previewInner"; import { PreviewContext, PreviewContextProps } from "./previewContext"; import ImageFoundation, { ImageAdapter } from "@douyinfe/semi-foundation/image/imageFoundation"; import LocaleConsumer from "../locale/localeConsumer"; import { Locale } from "../locale/interface"; import { isBoolean, isObject, isUndefined } from "lodash"; import Skeleton from "../skeleton"; import "@douyinfe/semi-foundation/image/image.scss"; const prefixCls = cssClasses.PREFIX; export default class Image extends BaseComponent { static isSemiImage = true; static contextType = PreviewContext; static propTypes = { style: PropTypes.object, className: PropTypes.string, src: PropTypes.string, width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), alt: PropTypes.string, placeholder: PropTypes.node, fallback: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), preview: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), onLoad: PropTypes.func, onError: PropTypes.func, crossOrigin: PropTypes.string, imageID: PropTypes.number, } static defaultProps = { preview: true, }; get adapter(): ImageAdapter { return { ...super.adapter, getIsInGroup: () => this.isInGroup(), }; } context: PreviewContextProps; foundation: ImageFoundation; constructor(props: ImageProps) { super(props); this.state = { src: "", loadStatus: "loading", previewVisible: false, }; this.foundation = new ImageFoundation(this.adapter); } static getDerivedStateFromProps(props: ImageProps, state: ImageStates) { const willUpdateStates: Partial = {}; if (props.src !== state.src) { willUpdateStates.src = props.src; willUpdateStates.loadStatus = "loading"; } if (isObject(props.preview)) { const { visible } = props.preview; if (isBoolean(visible)) { willUpdateStates.previewVisible = visible; } } return willUpdateStates; } isInGroup() { return Boolean(this.context && this.context.isGroup); } isLazyLoad() { if (this.context) { return this.context.lazyLoad; } return false; } handleClick = (e) => { this.foundation.handleClick(e); }; handleLoaded = (e) => { this.foundation.handleLoaded(e); } handleError = (e) => { this.foundation.handleError(e); } handlePreviewVisibleChange = (visible: boolean) => { this.foundation.handlePreviewVisibleChange(visible); } renderDefaultLoading = () => { const { width, height } = this.props; return ( ); }; renderDefaultError = () => { const prefixClsName = `${prefixCls}-status`; return (
); }; renderLoad = () => { const prefixClsName = `${prefixCls}-status`; const { placeholder } = this.props; return ( placeholder ? (
{placeholder}
) : this.renderDefaultLoading() ); } renderError = () => { const { fallback } = this.props; const prefixClsName = `${prefixCls}-status`; const fallbackNode = typeof fallback === "string" ? (fallback) : fallback; return ( fallback ? (
{fallbackNode}
) :this.renderDefaultError() ); } renderExtra = () => { const { loadStatus } = this.state; return (
{loadStatus === "error" && this.renderError()} {loadStatus === "loading" && this.renderLoad()}
); } getLocalTextByKey = (key: string) => ( componentName="Image" > {(locale: Locale["Image"]) => locale[key]} ); renderMask = () => (
{this.getLocalTextByKey("preview")}
) render() { const { src, loadStatus, previewVisible } = this.state; const { src: picSrc, width, height, alt, style, className, crossOrigin, preview, fallback, placeholder, imageID, ...restProps } = this.props; const outerStyle = Object.assign({ width, height }, style); const outerCls = cls(prefixCls, className); const canPreview = loadStatus === "success" && preview && !this.isInGroup(); const showPreviewCursor = preview && loadStatus === "success"; const previewSrc = isObject(preview) ? ((preview as any).src ?? src) : src; const previewProps = isObject(preview) ? preview : {}; return ( // eslint-disable jsx-a11y/no-static-element-interactions // eslint-disable jsx-a11y/click-events-have-key-events
{alt} {loadStatus !== "success" && this.renderExtra()} {canPreview && }
); } }