1
This commit is contained in:
+191
@@ -0,0 +1,191 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user