191 lines
6.2 KiB
JavaScript
191 lines
6.2 KiB
JavaScript
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
import useControlledState from "@rc-component/util/es/hooks/useControlledState";
|
|
import { clsx } from 'clsx';
|
|
import * as React from 'react';
|
|
import { useContext, useMemo, useState } from 'react';
|
|
import Preview from "./Preview";
|
|
import PreviewGroup from "./PreviewGroup";
|
|
import { COMMON_PROPS } from "./common";
|
|
import { PreviewGroupContext } from "./context";
|
|
import useRegisterImage from "./hooks/useRegisterImage";
|
|
import useStatus from "./hooks/useStatus";
|
|
const ImageInternal = props => {
|
|
const {
|
|
// Misc
|
|
prefixCls = 'rc-image',
|
|
previewPrefixCls = `${prefixCls}-preview`,
|
|
// Style
|
|
rootClassName,
|
|
className,
|
|
style,
|
|
classNames = {},
|
|
styles = {},
|
|
width,
|
|
height,
|
|
// Image
|
|
src: imgSrc,
|
|
alt,
|
|
placeholder,
|
|
fallback,
|
|
// Preview
|
|
preview = true,
|
|
// Events
|
|
onClick,
|
|
onError,
|
|
onKeyDown,
|
|
...otherProps
|
|
} = props;
|
|
const groupContext = useContext(PreviewGroupContext);
|
|
|
|
// ========================== Preview ===========================
|
|
const canPreview = !!preview;
|
|
const {
|
|
src: previewSrc,
|
|
open: previewOpen,
|
|
onOpenChange: onPreviewOpenChange,
|
|
cover,
|
|
rootClassName: previewRootClassName,
|
|
...restProps
|
|
} = preview && typeof preview === 'object' ? preview : {};
|
|
const coverPlacement = typeof cover === 'object' && cover.placement ? cover.placement || 'center' : 'center';
|
|
const coverNode = typeof cover === 'object' && cover.coverNode ? cover.coverNode : cover;
|
|
|
|
// ============================ Open ============================
|
|
const [isShowPreview, setShowPreview] = useControlledState(!!previewOpen, previewOpen);
|
|
const [mousePosition, setMousePosition] = useState(null);
|
|
const triggerPreviewOpen = nextOpen => {
|
|
setShowPreview(nextOpen);
|
|
onPreviewOpenChange?.(nextOpen);
|
|
};
|
|
const onPreviewClose = () => {
|
|
triggerPreviewOpen(false);
|
|
};
|
|
|
|
// ========================= ImageProps =========================
|
|
const isCustomPlaceholder = placeholder && placeholder !== true;
|
|
const src = previewSrc ?? imgSrc;
|
|
const [getImgRef, srcAndOnload, status] = useStatus({
|
|
src: imgSrc,
|
|
isCustomPlaceholder,
|
|
fallback
|
|
});
|
|
const imgCommonProps = useMemo(() => {
|
|
const obj = {};
|
|
COMMON_PROPS.forEach(prop => {
|
|
if (props[prop] !== undefined) {
|
|
obj[prop] = props[prop];
|
|
}
|
|
});
|
|
return obj;
|
|
}, COMMON_PROPS.map(prop => props[prop]));
|
|
|
|
// ========================== Register ==========================
|
|
const registerData = useMemo(() => ({
|
|
...imgCommonProps,
|
|
src
|
|
}), [src, imgCommonProps]);
|
|
const imageId = useRegisterImage(canPreview, registerData);
|
|
|
|
// ========================== Preview ===========================
|
|
const onPreview = e => {
|
|
const rect = e.target.getBoundingClientRect();
|
|
const left = rect.x + rect.width / 2;
|
|
const top = rect.y + rect.height / 2;
|
|
if (groupContext) {
|
|
groupContext.onPreview(imageId, src, left, top);
|
|
} else {
|
|
setMousePosition({
|
|
x: left,
|
|
y: top
|
|
});
|
|
triggerPreviewOpen(true);
|
|
}
|
|
onClick?.(e);
|
|
};
|
|
|
|
// ======================= Keyboard Preview =====================
|
|
const onPreviewKeyDown = event => {
|
|
onKeyDown?.(event);
|
|
if (!canPreview) {
|
|
return;
|
|
}
|
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
event.preventDefault();
|
|
const rect = event.target.getBoundingClientRect();
|
|
const left = rect.x + rect.width / 2;
|
|
const top = rect.y + rect.height / 2;
|
|
if (groupContext) {
|
|
groupContext.onPreview(imageId, src, left, top);
|
|
} else {
|
|
setMousePosition({
|
|
x: left,
|
|
y: top
|
|
});
|
|
triggerPreviewOpen(true);
|
|
}
|
|
}
|
|
};
|
|
|
|
// =========================== Render ===========================
|
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", _extends({}, otherProps, {
|
|
className: clsx(prefixCls, rootClassName, classNames.root, {
|
|
[`${prefixCls}-error`]: status === 'error'
|
|
}),
|
|
onClick: canPreview ? onPreview : onClick,
|
|
role: canPreview ? 'button' : otherProps.role,
|
|
tabIndex: canPreview && otherProps.tabIndex == null ? 0 : otherProps.tabIndex,
|
|
"aria-label": canPreview ? otherProps['aria-label'] ?? alt : otherProps['aria-label'],
|
|
onKeyDown: onPreviewKeyDown,
|
|
style: {
|
|
width,
|
|
height,
|
|
...styles.root
|
|
}
|
|
}), /*#__PURE__*/React.createElement("img", _extends({}, imgCommonProps, {
|
|
className: clsx(`${prefixCls}-img`, {
|
|
[`${prefixCls}-img-placeholder`]: placeholder === true
|
|
}, classNames.image, className),
|
|
style: {
|
|
height,
|
|
...styles.image,
|
|
...style
|
|
},
|
|
ref: getImgRef
|
|
}, srcAndOnload, {
|
|
width: width,
|
|
height: height,
|
|
onError: onError
|
|
})), status === 'loading' && /*#__PURE__*/React.createElement("div", {
|
|
"aria-hidden": "true",
|
|
className: `${prefixCls}-placeholder`
|
|
}, placeholder), cover !== false && canPreview && /*#__PURE__*/React.createElement("div", {
|
|
className: clsx(`${prefixCls}-cover`, classNames.cover, `${prefixCls}-cover-${coverPlacement}`),
|
|
style: {
|
|
display: style?.display === 'none' ? 'none' : undefined,
|
|
...styles.cover
|
|
}
|
|
}, coverNode)), !groupContext && canPreview && /*#__PURE__*/React.createElement(Preview, _extends({
|
|
"aria-hidden": !isShowPreview,
|
|
open: isShowPreview,
|
|
prefixCls: previewPrefixCls,
|
|
onClose: onPreviewClose,
|
|
mousePosition: mousePosition,
|
|
src: src,
|
|
alt: alt,
|
|
imageInfo: {
|
|
width,
|
|
height
|
|
},
|
|
fallback: fallback,
|
|
imgCommonProps: imgCommonProps
|
|
}, restProps, {
|
|
classNames: classNames?.popup,
|
|
styles: styles?.popup,
|
|
rootClassName: clsx(previewRootClassName, rootClassName)
|
|
})));
|
|
};
|
|
ImageInternal.PreviewGroup = PreviewGroup;
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
ImageInternal.displayName = 'Image';
|
|
}
|
|
export default ImageInternal; |