1
This commit is contained in:
+47
@@ -0,0 +1,47 @@
|
||||
import * as React from 'react';
|
||||
import type { InternalPreviewConfig, PreviewSemanticName, ToolbarRenderInfoType } from './Preview';
|
||||
import PreviewGroup from './PreviewGroup';
|
||||
import type { TransformType } from './hooks/useImageTransform';
|
||||
export interface ImgInfo {
|
||||
url: string;
|
||||
alt: string;
|
||||
width: string | number;
|
||||
height: string | number;
|
||||
}
|
||||
export interface CoverConfig {
|
||||
coverNode?: React.ReactNode;
|
||||
placement?: 'top' | 'bottom' | 'center';
|
||||
}
|
||||
export interface PreviewConfig extends Omit<InternalPreviewConfig, 'countRender'> {
|
||||
cover?: React.ReactNode | CoverConfig;
|
||||
imageRender?: (originalNode: React.ReactElement, info: {
|
||||
transform: TransformType;
|
||||
image: ImgInfo;
|
||||
}) => React.ReactNode;
|
||||
actionsRender?: (originalNode: React.ReactElement, info: Omit<ToolbarRenderInfoType, 'current' | 'total'>) => React.ReactNode;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
}
|
||||
export type SemanticName = 'root' | 'image' | 'cover';
|
||||
export interface ImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'placeholder' | 'onClick' | 'onKeyDown'> {
|
||||
prefixCls?: string;
|
||||
previewPrefixCls?: string;
|
||||
rootClassName?: string;
|
||||
classNames?: Partial<Record<SemanticName, string> & {
|
||||
popup?: Partial<Record<PreviewSemanticName, string>>;
|
||||
}>;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties> & {
|
||||
popup?: Partial<Record<PreviewSemanticName, React.CSSProperties>>;
|
||||
}>;
|
||||
src?: string;
|
||||
placeholder?: React.ReactNode;
|
||||
fallback?: string;
|
||||
preview?: boolean | PreviewConfig;
|
||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||
onError?: (e: React.SyntheticEvent<HTMLImageElement, Event>) => void;
|
||||
onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
|
||||
}
|
||||
interface CompoundedComponent<P> extends React.FC<P> {
|
||||
PreviewGroup: typeof PreviewGroup;
|
||||
}
|
||||
declare const ImageInternal: CompoundedComponent<ImageProps>;
|
||||
export default ImageInternal;
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _useControlledState = _interopRequireDefault(require("@rc-component/util/lib/hooks/useControlledState"));
|
||||
var _clsx = require("clsx");
|
||||
var _react = _interopRequireWildcard(require("react"));
|
||||
var React = _react;
|
||||
var _Preview = _interopRequireDefault(require("./Preview"));
|
||||
var _PreviewGroup = _interopRequireDefault(require("./PreviewGroup"));
|
||||
var _common = require("./common");
|
||||
var _context = require("./context");
|
||||
var _useRegisterImage = _interopRequireDefault(require("./hooks/useRegisterImage"));
|
||||
var _useStatus = _interopRequireDefault(require("./hooks/useStatus"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
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); }
|
||||
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 = (0, _react.useContext)(_context.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] = (0, _useControlledState.default)(!!previewOpen, previewOpen);
|
||||
const [mousePosition, setMousePosition] = (0, _react.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] = (0, _useStatus.default)({
|
||||
src: imgSrc,
|
||||
isCustomPlaceholder,
|
||||
fallback
|
||||
});
|
||||
const imgCommonProps = (0, _react.useMemo)(() => {
|
||||
const obj = {};
|
||||
_common.COMMON_PROPS.forEach(prop => {
|
||||
if (props[prop] !== undefined) {
|
||||
obj[prop] = props[prop];
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
}, _common.COMMON_PROPS.map(prop => props[prop]));
|
||||
|
||||
// ========================== Register ==========================
|
||||
const registerData = (0, _react.useMemo)(() => ({
|
||||
...imgCommonProps,
|
||||
src
|
||||
}), [src, imgCommonProps]);
|
||||
const imageId = (0, _useRegisterImage.default)(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: (0, _clsx.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: (0, _clsx.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: (0, _clsx.clsx)(`${prefixCls}-cover`, classNames.cover, `${prefixCls}-cover-${coverPlacement}`),
|
||||
style: {
|
||||
display: style?.display === 'none' ? 'none' : undefined,
|
||||
...styles.cover
|
||||
}
|
||||
}, coverNode)), !groupContext && canPreview && /*#__PURE__*/React.createElement(_Preview.default, _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: (0, _clsx.clsx)(previewRootClassName, rootClassName)
|
||||
})));
|
||||
};
|
||||
ImageInternal.PreviewGroup = _PreviewGroup.default;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
ImageInternal.displayName = 'Image';
|
||||
}
|
||||
var _default = exports.default = ImageInternal;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
export interface CloseBtnProps {
|
||||
prefixCls: string;
|
||||
icon?: React.ReactNode;
|
||||
onClick: React.MouseEventHandler<HTMLButtonElement>;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
export default function CloseBtn(props: CloseBtnProps): React.JSX.Element;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = CloseBtn;
|
||||
var _clsx = require("clsx");
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function CloseBtn(props) {
|
||||
const {
|
||||
prefixCls,
|
||||
icon,
|
||||
onClick,
|
||||
className,
|
||||
style
|
||||
} = props;
|
||||
return /*#__PURE__*/React.createElement("button", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-close`, className),
|
||||
style: style,
|
||||
onClick: onClick
|
||||
}, icon);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import * as React from 'react';
|
||||
import type { Actions, PreviewProps } from '.';
|
||||
import type { ImgInfo } from '../Image';
|
||||
import type { TransformType } from '../hooks/useImageTransform';
|
||||
export type FooterSemanticName = 'footer' | 'actions';
|
||||
export interface FooterProps extends Actions {
|
||||
prefixCls: string;
|
||||
showProgress: boolean;
|
||||
countRender?: PreviewProps['countRender'];
|
||||
actionsRender?: PreviewProps['actionsRender'];
|
||||
current: number;
|
||||
count: number;
|
||||
showSwitch: boolean;
|
||||
icons: PreviewProps['icons'];
|
||||
scale: number;
|
||||
minScale: number;
|
||||
maxScale: number;
|
||||
image: ImgInfo;
|
||||
transform: TransformType;
|
||||
classNames: Partial<Record<FooterSemanticName, string>>;
|
||||
styles: Partial<Record<FooterSemanticName, React.CSSProperties>>;
|
||||
}
|
||||
export default function Footer(props: FooterProps): React.JSX.Element;
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = Footer;
|
||||
var _clsx = require("clsx");
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function Footer(props) {
|
||||
// 修改解构,添加缺失的属性,并提供默认值
|
||||
const {
|
||||
prefixCls,
|
||||
showProgress,
|
||||
current,
|
||||
count,
|
||||
showSwitch,
|
||||
// Style
|
||||
classNames,
|
||||
styles,
|
||||
// render
|
||||
icons,
|
||||
image,
|
||||
transform,
|
||||
countRender,
|
||||
actionsRender,
|
||||
// Scale
|
||||
scale,
|
||||
minScale,
|
||||
maxScale,
|
||||
// Actions
|
||||
onActive,
|
||||
onFlipY,
|
||||
onFlipX,
|
||||
onRotateLeft,
|
||||
onRotateRight,
|
||||
onZoomOut,
|
||||
onZoomIn,
|
||||
onClose,
|
||||
onReset
|
||||
} = props;
|
||||
const {
|
||||
left,
|
||||
right,
|
||||
prev,
|
||||
next,
|
||||
flipY,
|
||||
flipX,
|
||||
rotateLeft,
|
||||
rotateRight,
|
||||
zoomOut,
|
||||
zoomIn
|
||||
} = icons;
|
||||
|
||||
// ========================== Render ==========================
|
||||
// >>>>> Progress
|
||||
const progressNode = showProgress && /*#__PURE__*/React.createElement("div", {
|
||||
className: `${prefixCls}-progress`
|
||||
}, countRender ? countRender(current + 1, count) : /*#__PURE__*/React.createElement("bdi", null, `${current + 1} / ${count}`));
|
||||
|
||||
// >>>>> Actions
|
||||
const actionCls = `${prefixCls}-actions-action`;
|
||||
const renderOperation = ({
|
||||
type,
|
||||
disabled,
|
||||
onClick,
|
||||
icon
|
||||
}) => {
|
||||
return /*#__PURE__*/React.createElement("button", {
|
||||
type: "button",
|
||||
key: type,
|
||||
className: (0, _clsx.clsx)(actionCls, `${actionCls}-${type}`, {
|
||||
[`${actionCls}-disabled`]: !!disabled
|
||||
}),
|
||||
onClick: onClick,
|
||||
disabled: !!disabled,
|
||||
"aria-label": type
|
||||
}, icon);
|
||||
};
|
||||
const switchPrevNode = showSwitch ? renderOperation({
|
||||
icon: prev ?? left,
|
||||
onClick: () => onActive(-1),
|
||||
type: 'prev',
|
||||
disabled: current === 0
|
||||
}) : undefined;
|
||||
const switchNextNode = showSwitch ? renderOperation({
|
||||
icon: next ?? right,
|
||||
onClick: () => onActive(1),
|
||||
type: 'next',
|
||||
disabled: current === count - 1
|
||||
}) : undefined;
|
||||
const flipYNode = renderOperation({
|
||||
icon: flipY,
|
||||
onClick: onFlipY,
|
||||
type: 'flipY'
|
||||
});
|
||||
const flipXNode = renderOperation({
|
||||
icon: flipX,
|
||||
onClick: onFlipX,
|
||||
type: 'flipX'
|
||||
});
|
||||
const rotateLeftNode = renderOperation({
|
||||
icon: rotateLeft,
|
||||
onClick: onRotateLeft,
|
||||
type: 'rotateLeft'
|
||||
});
|
||||
const rotateRightNode = renderOperation({
|
||||
icon: rotateRight,
|
||||
onClick: onRotateRight,
|
||||
type: 'rotateRight'
|
||||
});
|
||||
const zoomOutNode = renderOperation({
|
||||
icon: zoomOut,
|
||||
onClick: onZoomOut,
|
||||
type: 'zoomOut',
|
||||
disabled: scale <= minScale
|
||||
});
|
||||
const zoomInNode = renderOperation({
|
||||
icon: zoomIn,
|
||||
onClick: onZoomIn,
|
||||
type: 'zoomIn',
|
||||
disabled: scale === maxScale
|
||||
});
|
||||
const actionsNode = /*#__PURE__*/React.createElement("div", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-actions`, classNames.actions),
|
||||
style: styles.actions
|
||||
}, flipYNode, flipXNode, rotateLeftNode, rotateRightNode, zoomOutNode, zoomInNode);
|
||||
|
||||
// >>>>> Render
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-footer`, classNames.footer),
|
||||
style: styles.footer
|
||||
}, progressNode, actionsRender ? actionsRender(actionsNode, {
|
||||
icons: {
|
||||
prevIcon: switchPrevNode,
|
||||
nextIcon: switchNextNode,
|
||||
flipYIcon: flipYNode,
|
||||
flipXIcon: flipXNode,
|
||||
rotateLeftIcon: rotateLeftNode,
|
||||
rotateRightIcon: rotateRightNode,
|
||||
zoomOutIcon: zoomOutNode,
|
||||
zoomInIcon: zoomInNode
|
||||
},
|
||||
actions: {
|
||||
onActive,
|
||||
onFlipY,
|
||||
onFlipX,
|
||||
onRotateLeft,
|
||||
onRotateRight,
|
||||
onZoomOut,
|
||||
onZoomIn,
|
||||
onReset,
|
||||
onClose
|
||||
},
|
||||
transform,
|
||||
current,
|
||||
total: count,
|
||||
image
|
||||
}) : actionsNode);
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import type { OperationIcons } from '.';
|
||||
export interface PrevNextProps {
|
||||
prefixCls: string;
|
||||
onActive: (offset: number) => void;
|
||||
current: number;
|
||||
count: number;
|
||||
icons: OperationIcons;
|
||||
}
|
||||
export default function PrevNext(props: PrevNextProps): React.JSX.Element;
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = PrevNext;
|
||||
var _clsx = require("clsx");
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function PrevNext(props) {
|
||||
const {
|
||||
prefixCls,
|
||||
onActive,
|
||||
current,
|
||||
count,
|
||||
icons: {
|
||||
left,
|
||||
right,
|
||||
prev,
|
||||
next
|
||||
}
|
||||
} = props;
|
||||
const switchCls = `${prefixCls}-switch`;
|
||||
const prevDisabled = current === 0;
|
||||
const nextDisabled = current === count - 1;
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
|
||||
className: (0, _clsx.clsx)(switchCls, `${switchCls}-prev`, {
|
||||
[`${switchCls}-disabled`]: prevDisabled
|
||||
}),
|
||||
onClick: () => onActive(-1),
|
||||
disabled: prevDisabled
|
||||
}, prev ?? left), /*#__PURE__*/React.createElement("button", {
|
||||
type: "button",
|
||||
className: (0, _clsx.clsx)(switchCls, `${switchCls}-next`, {
|
||||
[`${switchCls}-disabled`]: nextDisabled
|
||||
}),
|
||||
onClick: () => onActive(1),
|
||||
disabled: nextDisabled
|
||||
}, next ?? right));
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
import { type PortalProps } from '@rc-component/portal';
|
||||
import React from 'react';
|
||||
import type { TransformAction, TransformType } from '../hooks/useImageTransform';
|
||||
import type { ImgInfo } from '../Image';
|
||||
import { type FooterSemanticName } from './Footer';
|
||||
export type PreviewSemanticName = 'root' | 'mask' | 'body' | 'close' | FooterSemanticName;
|
||||
export interface OperationIcons {
|
||||
rotateLeft?: React.ReactNode;
|
||||
rotateRight?: React.ReactNode;
|
||||
zoomIn?: React.ReactNode;
|
||||
zoomOut?: React.ReactNode;
|
||||
close?: React.ReactNode;
|
||||
prev?: React.ReactNode;
|
||||
next?: React.ReactNode;
|
||||
/** @deprecated Please use `prev` instead */
|
||||
left?: React.ReactNode;
|
||||
/** @deprecated Please use `next` instead */
|
||||
right?: React.ReactNode;
|
||||
flipX?: React.ReactNode;
|
||||
flipY?: React.ReactNode;
|
||||
}
|
||||
export interface Actions {
|
||||
onActive: (offset: number) => void;
|
||||
onFlipY: () => void;
|
||||
onFlipX: () => void;
|
||||
onRotateLeft: () => void;
|
||||
onRotateRight: () => void;
|
||||
onZoomOut: () => void;
|
||||
onZoomIn: () => void;
|
||||
onClose: () => void;
|
||||
onReset: () => void;
|
||||
}
|
||||
export type ToolbarRenderInfoType = {
|
||||
icons: {
|
||||
prevIcon?: React.ReactNode;
|
||||
nextIcon?: React.ReactNode;
|
||||
flipYIcon: React.ReactNode;
|
||||
flipXIcon: React.ReactNode;
|
||||
rotateLeftIcon: React.ReactNode;
|
||||
rotateRightIcon: React.ReactNode;
|
||||
zoomOutIcon: React.ReactNode;
|
||||
zoomInIcon: React.ReactNode;
|
||||
};
|
||||
actions: Actions;
|
||||
transform: TransformType;
|
||||
current: number;
|
||||
total: number;
|
||||
image: ImgInfo;
|
||||
};
|
||||
export interface InternalPreviewConfig {
|
||||
/** Better to use `classNames.root` instead */
|
||||
rootClassName?: string;
|
||||
src?: string;
|
||||
alt?: string;
|
||||
scaleStep?: number;
|
||||
minScale?: number;
|
||||
maxScale?: number;
|
||||
motionName?: string;
|
||||
open?: boolean;
|
||||
getContainer?: PortalProps['getContainer'];
|
||||
zIndex?: number;
|
||||
maskClosable?: boolean;
|
||||
afterOpenChange?: (open: boolean) => void;
|
||||
/** Whether to trap focus within the preview when open. Default is true. */
|
||||
focusTrap?: boolean;
|
||||
movable?: boolean;
|
||||
icons?: OperationIcons;
|
||||
closeIcon?: React.ReactNode;
|
||||
onTransform?: (info: {
|
||||
transform: TransformType;
|
||||
action: TransformAction;
|
||||
}) => void;
|
||||
countRender?: (current: number, total: number) => React.ReactNode;
|
||||
imageRender?: (originalNode: React.ReactElement, info: {
|
||||
transform: TransformType;
|
||||
current?: number;
|
||||
image: ImgInfo;
|
||||
}) => React.ReactNode;
|
||||
actionsRender?: (originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode;
|
||||
}
|
||||
export interface PreviewProps extends InternalPreviewConfig {
|
||||
prefixCls: string;
|
||||
classNames?: Partial<Record<PreviewSemanticName, string>>;
|
||||
styles?: Partial<Record<PreviewSemanticName, React.CSSProperties>>;
|
||||
imageInfo?: {
|
||||
width: number | string;
|
||||
height: number | string;
|
||||
};
|
||||
fallback?: string;
|
||||
imgCommonProps?: React.ImgHTMLAttributes<HTMLImageElement>;
|
||||
width?: string | number;
|
||||
height?: string | number;
|
||||
current?: number;
|
||||
count?: number;
|
||||
onChange?: (current: number, prev: number) => void;
|
||||
onClose?: () => void;
|
||||
mousePosition: null | {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}
|
||||
declare const Preview: React.FC<PreviewProps>;
|
||||
export default Preview;
|
||||
+371
@@ -0,0 +1,371 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _motion = _interopRequireDefault(require("@rc-component/motion"));
|
||||
var _portal = _interopRequireDefault(require("@rc-component/portal"));
|
||||
var _util = require("@rc-component/util");
|
||||
var _focus = require("@rc-component/util/lib/Dom/focus");
|
||||
var _useLayoutEffect = _interopRequireDefault(require("@rc-component/util/lib/hooks/useLayoutEffect"));
|
||||
var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode"));
|
||||
var _clsx = require("clsx");
|
||||
var _react = _interopRequireWildcard(require("react"));
|
||||
var _context = require("../context");
|
||||
var _useImageTransform = _interopRequireDefault(require("../hooks/useImageTransform"));
|
||||
var _useMouseEvent = _interopRequireDefault(require("../hooks/useMouseEvent"));
|
||||
var _useStatus = _interopRequireDefault(require("../hooks/useStatus"));
|
||||
var _useTouchEvent = _interopRequireDefault(require("../hooks/useTouchEvent"));
|
||||
var _previewConfig = require("../previewConfig");
|
||||
var _CloseBtn = _interopRequireDefault(require("./CloseBtn"));
|
||||
var _Footer = _interopRequireDefault(require("./Footer"));
|
||||
var _PrevNext = _interopRequireDefault(require("./PrevNext"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
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); }
|
||||
// Note: if you want to add `action`,
|
||||
// pls contact @zombieJ or @thinkasany first.
|
||||
|
||||
const PreviewImage = ({
|
||||
fallback,
|
||||
src,
|
||||
imgRef,
|
||||
...props
|
||||
}) => {
|
||||
const [getImgRef, srcAndOnload] = (0, _useStatus.default)({
|
||||
src,
|
||||
fallback
|
||||
});
|
||||
return /*#__PURE__*/_react.default.createElement("img", _extends({
|
||||
ref: ref => {
|
||||
imgRef.current = ref;
|
||||
getImgRef(ref);
|
||||
}
|
||||
}, props, srcAndOnload));
|
||||
};
|
||||
const Preview = props => {
|
||||
const {
|
||||
prefixCls,
|
||||
rootClassName,
|
||||
src,
|
||||
alt,
|
||||
imageInfo,
|
||||
fallback,
|
||||
movable = true,
|
||||
onClose,
|
||||
open,
|
||||
afterOpenChange,
|
||||
maskClosable = true,
|
||||
icons = {},
|
||||
closeIcon,
|
||||
getContainer,
|
||||
current = 0,
|
||||
count = 1,
|
||||
countRender,
|
||||
scaleStep = 0.5,
|
||||
minScale = 1,
|
||||
maxScale = 50,
|
||||
motionName = 'fade',
|
||||
imageRender,
|
||||
imgCommonProps,
|
||||
actionsRender,
|
||||
onTransform,
|
||||
onChange,
|
||||
classNames = {},
|
||||
styles = {},
|
||||
mousePosition,
|
||||
zIndex,
|
||||
focusTrap = true
|
||||
} = props;
|
||||
const imgRef = (0, _react.useRef)();
|
||||
const wrapperRef = (0, _react.useRef)(null);
|
||||
const triggerRef = (0, _react.useRef)(null);
|
||||
const groupContext = (0, _react.useContext)(_context.PreviewGroupContext);
|
||||
const showLeftOrRightSwitches = groupContext && count > 1;
|
||||
const showOperationsProgress = groupContext && count >= 1;
|
||||
|
||||
// ======================== Transform =========================
|
||||
const [enableTransition, setEnableTransition] = (0, _react.useState)(true);
|
||||
const {
|
||||
transform,
|
||||
resetTransform,
|
||||
updateTransform,
|
||||
dispatchZoomChange
|
||||
} = (0, _useImageTransform.default)(imgRef, minScale, maxScale, onTransform);
|
||||
const {
|
||||
isMoving,
|
||||
onMouseDown,
|
||||
onWheel
|
||||
} = (0, _useMouseEvent.default)(imgRef, movable, open, scaleStep, transform, updateTransform, dispatchZoomChange);
|
||||
const {
|
||||
isTouching,
|
||||
onTouchStart,
|
||||
onTouchMove,
|
||||
onTouchEnd
|
||||
} = (0, _useTouchEvent.default)(imgRef, movable, open, minScale, transform, updateTransform, dispatchZoomChange);
|
||||
const {
|
||||
rotate,
|
||||
scale
|
||||
} = transform;
|
||||
(0, _react.useEffect)(() => {
|
||||
if (!enableTransition) {
|
||||
setEnableTransition(true);
|
||||
}
|
||||
}, [enableTransition]);
|
||||
(0, _react.useEffect)(() => {
|
||||
if (!open) {
|
||||
resetTransform('close');
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
// ========================== Image ===========================
|
||||
const onDoubleClick = event => {
|
||||
if (open) {
|
||||
if (scale !== 1) {
|
||||
updateTransform({
|
||||
x: 0,
|
||||
y: 0,
|
||||
scale: 1
|
||||
}, 'doubleClick');
|
||||
} else {
|
||||
dispatchZoomChange(_previewConfig.BASE_SCALE_RATIO + scaleStep, 'doubleClick', event.clientX, event.clientY);
|
||||
}
|
||||
}
|
||||
};
|
||||
const imgNode = /*#__PURE__*/_react.default.createElement(PreviewImage, _extends({}, imgCommonProps, {
|
||||
width: props.width,
|
||||
height: props.height,
|
||||
imgRef: imgRef,
|
||||
className: `${prefixCls}-img`,
|
||||
alt: alt,
|
||||
style: {
|
||||
transform: `translate3d(${transform.x}px, ${transform.y}px, 0) scale3d(${transform.flipX ? '-' : ''}${scale}, ${transform.flipY ? '-' : ''}${scale}, 1) rotate(${rotate}deg)`,
|
||||
transitionDuration: (!enableTransition || isTouching) && '0s'
|
||||
},
|
||||
fallback: fallback,
|
||||
src: src,
|
||||
onWheel: onWheel,
|
||||
onMouseDown: onMouseDown,
|
||||
onDoubleClick: onDoubleClick,
|
||||
onTouchStart: onTouchStart,
|
||||
onTouchMove: onTouchMove,
|
||||
onTouchEnd: onTouchEnd,
|
||||
onTouchCancel: onTouchEnd
|
||||
}));
|
||||
const image = {
|
||||
url: src,
|
||||
alt,
|
||||
...imageInfo
|
||||
};
|
||||
|
||||
// ======================== Operation =========================
|
||||
// >>>>> Actions
|
||||
const onZoomIn = () => {
|
||||
dispatchZoomChange(_previewConfig.BASE_SCALE_RATIO + scaleStep, 'zoomIn');
|
||||
};
|
||||
const onZoomOut = () => {
|
||||
dispatchZoomChange(_previewConfig.BASE_SCALE_RATIO / (_previewConfig.BASE_SCALE_RATIO + scaleStep), 'zoomOut');
|
||||
};
|
||||
const onRotateRight = () => {
|
||||
updateTransform({
|
||||
rotate: rotate + 90
|
||||
}, 'rotateRight');
|
||||
};
|
||||
const onRotateLeft = () => {
|
||||
updateTransform({
|
||||
rotate: rotate - 90
|
||||
}, 'rotateLeft');
|
||||
};
|
||||
const onFlipX = () => {
|
||||
updateTransform({
|
||||
flipX: !transform.flipX
|
||||
}, 'flipX');
|
||||
};
|
||||
const onFlipY = () => {
|
||||
updateTransform({
|
||||
flipY: !transform.flipY
|
||||
}, 'flipY');
|
||||
};
|
||||
const onReset = () => {
|
||||
resetTransform('reset');
|
||||
};
|
||||
const onActive = offset => {
|
||||
const nextCurrent = current + offset;
|
||||
if (nextCurrent >= 0 && nextCurrent <= count - 1) {
|
||||
setEnableTransition(false);
|
||||
resetTransform(offset < 0 ? 'prev' : 'next');
|
||||
onChange?.(nextCurrent, current);
|
||||
}
|
||||
};
|
||||
|
||||
// >>>>> Effect: Keyboard
|
||||
const onKeyDown = (0, _util.useEvent)(event => {
|
||||
if (open) {
|
||||
const {
|
||||
keyCode
|
||||
} = event;
|
||||
if (showLeftOrRightSwitches) {
|
||||
if (keyCode === _KeyCode.default.LEFT) {
|
||||
onActive(-1);
|
||||
} else if (keyCode === _KeyCode.default.RIGHT) {
|
||||
onActive(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
(0, _react.useEffect)(() => {
|
||||
if (open) {
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', onKeyDown);
|
||||
};
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
// ======================= Lock Scroll ========================
|
||||
const [lockScroll, setLockScroll] = (0, _react.useState)(false);
|
||||
_react.default.useEffect(() => {
|
||||
if (open) {
|
||||
setLockScroll(true);
|
||||
}
|
||||
}, [open]);
|
||||
const onVisibleChanged = nextVisible => {
|
||||
if (!nextVisible) {
|
||||
setLockScroll(false);
|
||||
|
||||
// Restore focus to the trigger element after leave animation
|
||||
triggerRef.current?.focus?.();
|
||||
triggerRef.current = null;
|
||||
}
|
||||
afterOpenChange?.(nextVisible);
|
||||
};
|
||||
|
||||
// ========================== Portal ==========================
|
||||
const [portalRender, setPortalRender] = (0, _react.useState)(false);
|
||||
(0, _useLayoutEffect.default)(() => {
|
||||
if (open) {
|
||||
setPortalRender(true);
|
||||
}
|
||||
}, [open]);
|
||||
const onEsc = ({
|
||||
top
|
||||
}) => {
|
||||
if (top) {
|
||||
onClose?.();
|
||||
}
|
||||
};
|
||||
|
||||
// =========================== Focus ============================
|
||||
(0, _useLayoutEffect.default)(() => {
|
||||
if (open) {
|
||||
triggerRef.current = document.activeElement;
|
||||
}
|
||||
}, [open]);
|
||||
(0, _focus.useLockFocus)(focusTrap && open && portalRender, () => wrapperRef.current);
|
||||
|
||||
// ========================== Render ==========================
|
||||
const bodyStyle = {
|
||||
...styles.body
|
||||
};
|
||||
if (mousePosition) {
|
||||
bodyStyle.transformOrigin = `${mousePosition.x}px ${mousePosition.y}px`;
|
||||
}
|
||||
return /*#__PURE__*/_react.default.createElement(_portal.default, {
|
||||
open: portalRender && open,
|
||||
autoDestroy: false,
|
||||
getContainer: getContainer,
|
||||
autoLock: lockScroll,
|
||||
onEsc: onEsc
|
||||
}, /*#__PURE__*/_react.default.createElement(_motion.default, {
|
||||
motionName: motionName,
|
||||
visible: portalRender && open,
|
||||
motionAppear: true,
|
||||
motionEnter: true,
|
||||
motionLeave: true,
|
||||
onVisibleChanged: onVisibleChanged
|
||||
}, ({
|
||||
className: motionClassName,
|
||||
style: motionStyle
|
||||
}) => {
|
||||
const mergedStyle = {
|
||||
...styles.root,
|
||||
...motionStyle
|
||||
};
|
||||
if (zIndex) {
|
||||
mergedStyle.zIndex = zIndex;
|
||||
}
|
||||
return /*#__PURE__*/_react.default.createElement("div", {
|
||||
ref: wrapperRef,
|
||||
className: (0, _clsx.clsx)(prefixCls, rootClassName, classNames.root, motionClassName, {
|
||||
[`${prefixCls}-movable`]: movable,
|
||||
[`${prefixCls}-moving`]: isMoving
|
||||
}),
|
||||
style: mergedStyle,
|
||||
role: "dialog",
|
||||
"aria-modal": "true",
|
||||
"aria-label": alt,
|
||||
tabIndex: -1
|
||||
}, /*#__PURE__*/_react.default.createElement("div", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-mask`, classNames.mask),
|
||||
style: styles.mask,
|
||||
onClick: maskClosable ? onClose : undefined
|
||||
}), /*#__PURE__*/_react.default.createElement("div", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-body`, classNames.body),
|
||||
style: bodyStyle
|
||||
}, imageRender ? imageRender(imgNode, {
|
||||
transform,
|
||||
image,
|
||||
...(groupContext ? {
|
||||
current
|
||||
} : {})
|
||||
}) : imgNode), closeIcon !== false && closeIcon !== null && /*#__PURE__*/_react.default.createElement(_CloseBtn.default, {
|
||||
prefixCls: prefixCls,
|
||||
icon: closeIcon === true ? icons.close : closeIcon || icons.close,
|
||||
onClick: onClose,
|
||||
className: classNames.close,
|
||||
style: styles.close
|
||||
}), showLeftOrRightSwitches && /*#__PURE__*/_react.default.createElement(_PrevNext.default, {
|
||||
prefixCls: prefixCls,
|
||||
current: current,
|
||||
count: count,
|
||||
icons: icons,
|
||||
onActive: onActive
|
||||
}), /*#__PURE__*/_react.default.createElement(_Footer.default, {
|
||||
prefixCls: prefixCls,
|
||||
showProgress: showOperationsProgress,
|
||||
current: current,
|
||||
count: count,
|
||||
showSwitch: showLeftOrRightSwitches
|
||||
// Style
|
||||
,
|
||||
classNames: classNames,
|
||||
styles: styles
|
||||
// Render
|
||||
,
|
||||
image: image,
|
||||
transform: transform,
|
||||
icons: icons,
|
||||
countRender: countRender,
|
||||
actionsRender: actionsRender
|
||||
// Scale
|
||||
,
|
||||
scale: scale,
|
||||
minScale: minScale,
|
||||
maxScale: maxScale
|
||||
// Actions
|
||||
,
|
||||
onActive: onActive,
|
||||
onFlipY: onFlipY,
|
||||
onFlipX: onFlipX,
|
||||
onRotateLeft: onRotateLeft,
|
||||
onRotateRight: onRotateRight,
|
||||
onZoomOut: onZoomOut,
|
||||
onZoomIn: onZoomIn,
|
||||
onClose: onClose,
|
||||
onReset: onReset
|
||||
}));
|
||||
}));
|
||||
};
|
||||
var _default = exports.default = Preview;
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import * as React from 'react';
|
||||
import type { ImgInfo } from './Image';
|
||||
import type { InternalPreviewConfig, PreviewProps, PreviewSemanticName } from './Preview';
|
||||
import type { TransformType } from './hooks/useImageTransform';
|
||||
import type { ImageElementProps } from './interface';
|
||||
export interface GroupPreviewConfig extends InternalPreviewConfig {
|
||||
current?: number;
|
||||
imageRender?: (originalNode: React.ReactElement, info: {
|
||||
transform: TransformType;
|
||||
current: number;
|
||||
image: ImgInfo;
|
||||
}) => React.ReactNode;
|
||||
onOpenChange?: (value: boolean, info: {
|
||||
current: number;
|
||||
}) => void;
|
||||
onChange?: (current: number, prevCurrent: number) => void;
|
||||
}
|
||||
export interface PreviewGroupProps {
|
||||
previewPrefixCls?: string;
|
||||
classNames?: {
|
||||
popup?: Partial<Record<PreviewSemanticName, string>>;
|
||||
};
|
||||
styles?: {
|
||||
popup?: Partial<Record<PreviewSemanticName, React.CSSProperties>>;
|
||||
};
|
||||
icons?: PreviewProps['icons'];
|
||||
items?: (string | ImageElementProps)[];
|
||||
fallback?: string;
|
||||
preview?: boolean | GroupPreviewConfig;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
declare const Group: React.FC<PreviewGroupProps>;
|
||||
export default Group;
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _useControlledState = _interopRequireDefault(require("@rc-component/util/lib/hooks/useControlledState"));
|
||||
var _useEvent = _interopRequireDefault(require("@rc-component/util/lib/hooks/useEvent"));
|
||||
var _react = _interopRequireWildcard(require("react"));
|
||||
var React = _react;
|
||||
var _Preview = _interopRequireDefault(require("./Preview"));
|
||||
var _context = require("./context");
|
||||
var _usePreviewItems = _interopRequireDefault(require("./hooks/usePreviewItems"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
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); }
|
||||
const Group = ({
|
||||
previewPrefixCls = 'rc-image-preview',
|
||||
classNames,
|
||||
styles,
|
||||
children,
|
||||
icons = {},
|
||||
items,
|
||||
preview,
|
||||
fallback
|
||||
}) => {
|
||||
const {
|
||||
open: previewOpen,
|
||||
onOpenChange,
|
||||
current: currentIndex,
|
||||
onChange,
|
||||
...restProps
|
||||
} = preview && typeof preview === 'object' ? preview : {};
|
||||
|
||||
// ========================== Items ===========================
|
||||
const [mergedItems, register, fromItems] = (0, _usePreviewItems.default)(items);
|
||||
|
||||
// ========================= Preview ==========================
|
||||
// >>> Index
|
||||
const [current, setCurrent] = (0, _useControlledState.default)(0, currentIndex);
|
||||
const [keepOpenIndex, setKeepOpenIndex] = (0, _react.useState)(false);
|
||||
|
||||
// >>> Image
|
||||
const {
|
||||
src,
|
||||
...imgCommonProps
|
||||
} = mergedItems[current]?.data || {};
|
||||
// >>> Visible
|
||||
const [isShowPreview, setShowPreview] = (0, _useControlledState.default)(!!previewOpen, previewOpen);
|
||||
const triggerShowPreview = (0, _useEvent.default)(next => {
|
||||
setShowPreview(next);
|
||||
if (next !== isShowPreview) {
|
||||
onOpenChange?.(next, {
|
||||
current
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// >>> Position
|
||||
const [mousePosition, setMousePosition] = (0, _react.useState)(null);
|
||||
const onPreviewFromImage = React.useCallback((id, imageSrc, mouseX, mouseY) => {
|
||||
const index = fromItems ? mergedItems.findIndex(item => item.data.src === imageSrc) : mergedItems.findIndex(item => item.id === id);
|
||||
setCurrent(index < 0 ? 0 : index);
|
||||
triggerShowPreview(true);
|
||||
setMousePosition({
|
||||
x: mouseX,
|
||||
y: mouseY
|
||||
});
|
||||
setKeepOpenIndex(true);
|
||||
}, [mergedItems, fromItems]);
|
||||
|
||||
// Reset current when reopen
|
||||
React.useEffect(() => {
|
||||
if (isShowPreview) {
|
||||
if (!keepOpenIndex) {
|
||||
setCurrent(0);
|
||||
}
|
||||
} else {
|
||||
setKeepOpenIndex(false);
|
||||
}
|
||||
}, [isShowPreview]);
|
||||
|
||||
// ========================== Events ==========================
|
||||
const onInternalChange = (next, prev) => {
|
||||
setCurrent(next);
|
||||
onChange?.(next, prev);
|
||||
};
|
||||
const onPreviewClose = () => {
|
||||
triggerShowPreview(false);
|
||||
setMousePosition(null);
|
||||
};
|
||||
|
||||
// ========================= Context ==========================
|
||||
const previewGroupContext = React.useMemo(() => ({
|
||||
register,
|
||||
onPreview: onPreviewFromImage
|
||||
}), [register, onPreviewFromImage]);
|
||||
|
||||
// ========================== Render ==========================
|
||||
return /*#__PURE__*/React.createElement(_context.PreviewGroupContext.Provider, {
|
||||
value: previewGroupContext
|
||||
}, children, /*#__PURE__*/React.createElement(_Preview.default, _extends({
|
||||
"aria-hidden": !isShowPreview,
|
||||
open: isShowPreview,
|
||||
prefixCls: previewPrefixCls,
|
||||
onClose: onPreviewClose,
|
||||
mousePosition: mousePosition,
|
||||
imgCommonProps: imgCommonProps,
|
||||
src: src,
|
||||
fallback: fallback,
|
||||
icons: icons,
|
||||
current: current,
|
||||
count: mergedItems.length,
|
||||
onChange: onInternalChange
|
||||
}, restProps, {
|
||||
classNames: classNames?.popup,
|
||||
styles: styles?.popup
|
||||
})));
|
||||
};
|
||||
var _default = exports.default = Group;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { ImageElementProps } from './interface';
|
||||
export declare const COMMON_PROPS: (keyof Omit<ImageElementProps, 'src'>)[];
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.COMMON_PROPS = void 0;
|
||||
const COMMON_PROPS = exports.COMMON_PROPS = ['crossOrigin', 'decoding', 'draggable', 'loading', 'referrerPolicy', 'sizes', 'srcSet', 'useMap', 'alt', 'fetchPriority'];
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import type { OnGroupPreview, RegisterImage } from './interface';
|
||||
export interface PreviewGroupContextProps {
|
||||
register: RegisterImage;
|
||||
onPreview: OnGroupPreview;
|
||||
}
|
||||
export declare const PreviewGroupContext: React.Context<PreviewGroupContextProps>;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.PreviewGroupContext = void 0;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
const PreviewGroupContext = exports.PreviewGroupContext = /*#__PURE__*/React.createContext(null);
|
||||
Generated
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Fix positon x,y point when
|
||||
*
|
||||
* Ele width && height < client
|
||||
* - Back origin
|
||||
*
|
||||
* - Ele width | height > clientWidth | clientHeight
|
||||
* - left | top > 0 -> Back 0
|
||||
* - left | top + width | height < clientWidth | clientHeight -> Back left | top + width | height === clientWidth | clientHeight
|
||||
*
|
||||
* Regardless of other
|
||||
*/
|
||||
export default function getFixScaleEleTransPosition(width: number, height: number, left: number, top: number): null | {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
Generated
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = getFixScaleEleTransPosition;
|
||||
var _util = require("./util");
|
||||
function fixPoint(key, start, width, clientWidth) {
|
||||
const startAddWidth = start + width;
|
||||
const offsetStart = (width - clientWidth) / 2;
|
||||
if (width > clientWidth) {
|
||||
if (start > 0) {
|
||||
return {
|
||||
[key]: offsetStart
|
||||
};
|
||||
}
|
||||
if (start < 0 && startAddWidth < clientWidth) {
|
||||
return {
|
||||
[key]: -offsetStart
|
||||
};
|
||||
}
|
||||
} else if (start < 0 || startAddWidth > clientWidth) {
|
||||
return {
|
||||
[key]: start < 0 ? offsetStart : -offsetStart
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix positon x,y point when
|
||||
*
|
||||
* Ele width && height < client
|
||||
* - Back origin
|
||||
*
|
||||
* - Ele width | height > clientWidth | clientHeight
|
||||
* - left | top > 0 -> Back 0
|
||||
* - left | top + width | height < clientWidth | clientHeight -> Back left | top + width | height === clientWidth | clientHeight
|
||||
*
|
||||
* Regardless of other
|
||||
*/
|
||||
function getFixScaleEleTransPosition(width, height, left, top) {
|
||||
const {
|
||||
width: clientWidth,
|
||||
height: clientHeight
|
||||
} = (0, _util.getClientSize)();
|
||||
let fixPos = null;
|
||||
if (width <= clientWidth && height <= clientHeight) {
|
||||
fixPos = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
} else if (width > clientWidth || height > clientHeight) {
|
||||
fixPos = {
|
||||
...fixPoint('x', left, width, clientWidth),
|
||||
...fixPoint('y', top, height, clientHeight)
|
||||
};
|
||||
}
|
||||
return fixPos;
|
||||
}
|
||||
Generated
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
/// <reference types="react" />
|
||||
export type TransformType = {
|
||||
x: number;
|
||||
y: number;
|
||||
rotate: number;
|
||||
scale: number;
|
||||
flipX: boolean;
|
||||
flipY: boolean;
|
||||
};
|
||||
export type TransformAction = 'flipY' | 'flipX' | 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'prev' | 'next' | 'wheel' | 'doubleClick' | 'move' | 'dragRebound' | 'touchZoom' | 'reset';
|
||||
export type UpdateTransformFunc = (newTransform: Partial<TransformType>, action: TransformAction) => void;
|
||||
export type DispatchZoomChangeFunc = (ratio: number, action: TransformAction, centerX?: number, centerY?: number, isTouch?: boolean) => void;
|
||||
export default function useImageTransform(imgRef: React.MutableRefObject<HTMLImageElement>, minScale: number, maxScale: number, onTransform: (info: {
|
||||
transform: TransformType;
|
||||
action: TransformAction;
|
||||
}) => void): {
|
||||
transform: {
|
||||
x: number;
|
||||
y: number;
|
||||
rotate: number;
|
||||
scale: number;
|
||||
flipX: boolean;
|
||||
flipY: boolean;
|
||||
};
|
||||
resetTransform: (action: TransformAction) => void;
|
||||
updateTransform: UpdateTransformFunc;
|
||||
dispatchZoomChange: DispatchZoomChangeFunc;
|
||||
};
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useImageTransform;
|
||||
var _util = require("../util");
|
||||
var _isEqual = _interopRequireDefault(require("@rc-component/util/lib/isEqual"));
|
||||
var _raf = _interopRequireDefault(require("@rc-component/util/lib/raf"));
|
||||
var _react = require("react");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
const initialTransform = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotate: 0,
|
||||
scale: 1,
|
||||
flipX: false,
|
||||
flipY: false
|
||||
};
|
||||
function useImageTransform(imgRef, minScale, maxScale, onTransform) {
|
||||
const frame = (0, _react.useRef)(null);
|
||||
const queue = (0, _react.useRef)([]);
|
||||
const [transform, setTransform] = (0, _react.useState)(initialTransform);
|
||||
const resetTransform = action => {
|
||||
setTransform(initialTransform);
|
||||
if (!(0, _isEqual.default)(initialTransform, transform)) {
|
||||
onTransform?.({
|
||||
transform: initialTransform,
|
||||
action
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/** Direct update transform */
|
||||
const updateTransform = (newTransform, action) => {
|
||||
if (frame.current === null) {
|
||||
queue.current = [];
|
||||
frame.current = (0, _raf.default)(() => {
|
||||
setTransform(preState => {
|
||||
let memoState = preState;
|
||||
queue.current.forEach(queueState => {
|
||||
memoState = {
|
||||
...memoState,
|
||||
...queueState
|
||||
};
|
||||
});
|
||||
frame.current = null;
|
||||
onTransform?.({
|
||||
transform: memoState,
|
||||
action
|
||||
});
|
||||
return memoState;
|
||||
});
|
||||
});
|
||||
}
|
||||
queue.current.push({
|
||||
...transform,
|
||||
...newTransform
|
||||
});
|
||||
};
|
||||
|
||||
/** Scale according to the position of centerX and centerY */
|
||||
const dispatchZoomChange = (ratio, action, centerX, centerY, isTouch) => {
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
offsetWidth,
|
||||
offsetHeight,
|
||||
offsetLeft,
|
||||
offsetTop
|
||||
} = imgRef.current;
|
||||
let newRatio = ratio;
|
||||
let newScale = transform.scale * ratio;
|
||||
if (newScale > maxScale) {
|
||||
newScale = maxScale;
|
||||
newRatio = maxScale / transform.scale;
|
||||
} else if (newScale < minScale) {
|
||||
// For mobile interactions, allow scaling down to the minimum scale.
|
||||
newScale = isTouch ? newScale : minScale;
|
||||
newRatio = newScale / transform.scale;
|
||||
}
|
||||
|
||||
/** Default center point scaling */
|
||||
const mergedCenterX = centerX ?? innerWidth / 2;
|
||||
const mergedCenterY = centerY ?? innerHeight / 2;
|
||||
const diffRatio = newRatio - 1;
|
||||
/** Deviation calculated from image size */
|
||||
const diffImgX = diffRatio * width * 0.5;
|
||||
const diffImgY = diffRatio * height * 0.5;
|
||||
/** The difference between the click position and the edge of the document */
|
||||
const diffOffsetLeft = diffRatio * (mergedCenterX - transform.x - offsetLeft);
|
||||
const diffOffsetTop = diffRatio * (mergedCenterY - transform.y - offsetTop);
|
||||
/** Final positioning */
|
||||
let newX = transform.x - (diffOffsetLeft - diffImgX);
|
||||
let newY = transform.y - (diffOffsetTop - diffImgY);
|
||||
|
||||
/**
|
||||
* When zooming the image
|
||||
* When the image size is smaller than the width and height of the window, the position is initialized
|
||||
*/
|
||||
if (ratio < 1 && newScale === 1) {
|
||||
const mergedWidth = offsetWidth * newScale;
|
||||
const mergedHeight = offsetHeight * newScale;
|
||||
const {
|
||||
width: clientWidth,
|
||||
height: clientHeight
|
||||
} = (0, _util.getClientSize)();
|
||||
if (mergedWidth <= clientWidth && mergedHeight <= clientHeight) {
|
||||
newX = 0;
|
||||
newY = 0;
|
||||
}
|
||||
}
|
||||
updateTransform({
|
||||
x: newX,
|
||||
y: newY,
|
||||
scale: newScale
|
||||
}, action);
|
||||
};
|
||||
return {
|
||||
transform,
|
||||
resetTransform,
|
||||
updateTransform,
|
||||
dispatchZoomChange
|
||||
};
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import type React from 'react';
|
||||
import type { DispatchZoomChangeFunc, TransformType, UpdateTransformFunc } from './useImageTransform';
|
||||
export default function useMouseEvent(imgRef: React.MutableRefObject<HTMLImageElement>, movable: boolean, open: boolean, scaleStep: number, transform: TransformType, updateTransform: UpdateTransformFunc, dispatchZoomChange: DispatchZoomChangeFunc): {
|
||||
isMoving: boolean;
|
||||
onMouseDown: React.MouseEventHandler<HTMLDivElement>;
|
||||
onMouseMove: (event: MouseEvent) => void;
|
||||
onMouseUp: () => void;
|
||||
onWheel: (event: React.WheelEvent<HTMLImageElement>) => void;
|
||||
};
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useMouseEvent;
|
||||
var _warning = require("@rc-component/util/lib/warning");
|
||||
var _react = require("react");
|
||||
var _getFixScaleEleTransPosition = _interopRequireDefault(require("../getFixScaleEleTransPosition"));
|
||||
var _previewConfig = require("../previewConfig");
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
function useMouseEvent(imgRef, movable, open, scaleStep, transform, updateTransform, dispatchZoomChange) {
|
||||
const {
|
||||
rotate,
|
||||
scale,
|
||||
x,
|
||||
y
|
||||
} = transform;
|
||||
const [isMoving, setMoving] = (0, _react.useState)(false);
|
||||
const startPositionInfo = (0, _react.useRef)({
|
||||
diffX: 0,
|
||||
diffY: 0,
|
||||
transformX: 0,
|
||||
transformY: 0
|
||||
});
|
||||
const onMouseDown = event => {
|
||||
// Only allow main button
|
||||
if (!movable || event.button !== 0) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
startPositionInfo.current = {
|
||||
diffX: event.pageX - x,
|
||||
diffY: event.pageY - y,
|
||||
transformX: x,
|
||||
transformY: y
|
||||
};
|
||||
setMoving(true);
|
||||
};
|
||||
const onMouseMove = event => {
|
||||
if (open && isMoving) {
|
||||
updateTransform({
|
||||
x: event.pageX - startPositionInfo.current.diffX,
|
||||
y: event.pageY - startPositionInfo.current.diffY
|
||||
}, 'move');
|
||||
}
|
||||
};
|
||||
const onMouseUp = () => {
|
||||
if (open && isMoving) {
|
||||
setMoving(false);
|
||||
|
||||
/** No need to restore the position when the picture is not moved, So as not to interfere with the click */
|
||||
const {
|
||||
transformX,
|
||||
transformY
|
||||
} = startPositionInfo.current;
|
||||
const hasChangedPosition = x !== transformX && y !== transformY;
|
||||
if (!hasChangedPosition) return;
|
||||
const width = imgRef.current.offsetWidth * scale;
|
||||
const height = imgRef.current.offsetHeight * scale;
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const {
|
||||
left,
|
||||
top
|
||||
} = imgRef.current.getBoundingClientRect();
|
||||
const isRotate = rotate % 180 !== 0;
|
||||
const fixState = (0, _getFixScaleEleTransPosition.default)(isRotate ? height : width, isRotate ? width : height, left, top);
|
||||
if (fixState) {
|
||||
updateTransform({
|
||||
...fixState
|
||||
}, 'dragRebound');
|
||||
}
|
||||
}
|
||||
};
|
||||
const onWheel = event => {
|
||||
if (!open || event.deltaY == 0) return;
|
||||
// Scale ratio depends on the deltaY size
|
||||
const scaleRatio = Math.abs(event.deltaY / 100);
|
||||
// Limit the maximum scale ratio
|
||||
const mergedScaleRatio = Math.min(scaleRatio, _previewConfig.WHEEL_MAX_SCALE_RATIO);
|
||||
// Scale the ratio each time
|
||||
let ratio = _previewConfig.BASE_SCALE_RATIO + mergedScaleRatio * scaleStep;
|
||||
if (event.deltaY > 0) {
|
||||
ratio = _previewConfig.BASE_SCALE_RATIO / ratio;
|
||||
}
|
||||
dispatchZoomChange(ratio, 'wheel', event.clientX, event.clientY);
|
||||
};
|
||||
(0, _react.useEffect)(() => {
|
||||
if (movable) {
|
||||
window.addEventListener('mouseup', onMouseUp, false);
|
||||
window.addEventListener('mousemove', onMouseMove, false);
|
||||
try {
|
||||
// Resolve if in iframe lost event
|
||||
/* istanbul ignore next */
|
||||
if (window.top !== window.self) {
|
||||
window.top.addEventListener('mouseup', onMouseUp, false);
|
||||
window.top.addEventListener('mousemove', onMouseMove, false);
|
||||
}
|
||||
} catch (error) {
|
||||
/* istanbul ignore next */
|
||||
(0, _warning.warning)(false, `[rc-image] ${error}`);
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('mouseup', onMouseUp);
|
||||
window.removeEventListener('mousemove', onMouseMove);
|
||||
|
||||
/* istanbul ignore next */
|
||||
try {
|
||||
window.top?.removeEventListener('mouseup', onMouseUp);
|
||||
window.top?.removeEventListener('mousemove', onMouseMove);
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
}, [open, isMoving, x, y, rotate, movable]);
|
||||
return {
|
||||
isMoving,
|
||||
onMouseDown,
|
||||
onMouseMove,
|
||||
onMouseUp,
|
||||
onWheel
|
||||
};
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import type { PreviewGroupProps } from '../PreviewGroup';
|
||||
import type { InternalItem, RegisterImage } from '../interface';
|
||||
export type Items = Omit<InternalItem, 'canPreview'>[];
|
||||
/**
|
||||
* Merge props provided `items` or context collected images
|
||||
*/
|
||||
export default function usePreviewItems(items?: PreviewGroupProps['items']): [items: Items, registerImage: RegisterImage, fromItems: boolean];
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = usePreviewItems;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _common = require("../common");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
/**
|
||||
* Merge props provided `items` or context collected images
|
||||
*/
|
||||
function usePreviewItems(items) {
|
||||
// Context collection image data
|
||||
const [images, setImages] = React.useState({});
|
||||
const registerImage = React.useCallback((id, data) => {
|
||||
setImages(imgs => ({
|
||||
...imgs,
|
||||
[id]: data
|
||||
}));
|
||||
return () => {
|
||||
setImages(imgs => {
|
||||
const cloneImgs = {
|
||||
...imgs
|
||||
};
|
||||
delete cloneImgs[id];
|
||||
return cloneImgs;
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
// items
|
||||
const mergedItems = React.useMemo(() => {
|
||||
// use `items` first
|
||||
if (items) {
|
||||
return items.map(item => {
|
||||
if (typeof item === 'string') {
|
||||
return {
|
||||
data: {
|
||||
src: item
|
||||
}
|
||||
};
|
||||
}
|
||||
const data = {};
|
||||
Object.keys(item).forEach(key => {
|
||||
if (['src', ..._common.COMMON_PROPS].includes(key)) {
|
||||
data[key] = item[key];
|
||||
}
|
||||
});
|
||||
return {
|
||||
data
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// use registered images secondly
|
||||
return Object.keys(images).reduce((total, id) => {
|
||||
const {
|
||||
canPreview,
|
||||
data
|
||||
} = images[id];
|
||||
if (canPreview) {
|
||||
total.push({
|
||||
data,
|
||||
id
|
||||
});
|
||||
}
|
||||
return total;
|
||||
}, []);
|
||||
}, [items, images]);
|
||||
return [mergedItems, registerImage, !!items];
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { ImageElementProps } from '../interface';
|
||||
export default function useRegisterImage(canPreview: boolean, data: ImageElementProps): string;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useRegisterImage;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
var _context = require("../context");
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
let uid = 0;
|
||||
function useRegisterImage(canPreview, data) {
|
||||
const [id] = React.useState(() => {
|
||||
uid += 1;
|
||||
return String(uid);
|
||||
});
|
||||
const groupContext = React.useContext(_context.PreviewGroupContext);
|
||||
const registerData = {
|
||||
data,
|
||||
canPreview
|
||||
};
|
||||
|
||||
// Keep order start
|
||||
// Resolve https://github.com/ant-design/ant-design/issues/28881
|
||||
// Only need unRegister when component unMount
|
||||
React.useEffect(() => {
|
||||
if (groupContext) {
|
||||
return groupContext.register(id, registerData);
|
||||
}
|
||||
}, []);
|
||||
React.useEffect(() => {
|
||||
if (groupContext) {
|
||||
groupContext.register(id, registerData);
|
||||
}
|
||||
}, [canPreview, data]);
|
||||
return id;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
type ImageStatus = 'normal' | 'error' | 'loading';
|
||||
export default function useStatus({ src, isCustomPlaceholder, fallback, }: {
|
||||
src: string;
|
||||
isCustomPlaceholder?: boolean;
|
||||
fallback?: string;
|
||||
}): readonly [(img?: HTMLImageElement) => void, {
|
||||
src: string;
|
||||
onLoad?: undefined;
|
||||
} | {
|
||||
onLoad: () => void;
|
||||
src: string;
|
||||
}, ImageStatus];
|
||||
export {};
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useStatus;
|
||||
var _react = require("react");
|
||||
var _util = require("../util");
|
||||
function useStatus({
|
||||
src,
|
||||
isCustomPlaceholder,
|
||||
fallback
|
||||
}) {
|
||||
const [status, setStatus] = (0, _react.useState)(isCustomPlaceholder ? 'loading' : 'normal');
|
||||
const isLoaded = (0, _react.useRef)(false);
|
||||
const isError = status === 'error';
|
||||
|
||||
// https://github.com/react-component/image/pull/187
|
||||
(0, _react.useEffect)(() => {
|
||||
let isCurrentSrc = true;
|
||||
(0, _util.isImageValid)(src).then(isValid => {
|
||||
// https://github.com/ant-design/ant-design/issues/44948
|
||||
// If src changes, the previous setStatus should not be triggered
|
||||
if (!isValid && isCurrentSrc) {
|
||||
setStatus('error');
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
isCurrentSrc = false;
|
||||
};
|
||||
}, [src]);
|
||||
(0, _react.useEffect)(() => {
|
||||
if (isCustomPlaceholder && !isLoaded.current) {
|
||||
setStatus('loading');
|
||||
} else if (isError) {
|
||||
setStatus('normal');
|
||||
}
|
||||
}, [src]);
|
||||
const onLoad = () => {
|
||||
setStatus('normal');
|
||||
};
|
||||
const getImgRef = img => {
|
||||
isLoaded.current = false;
|
||||
if (status === 'loading' && img?.complete && (img.naturalWidth || img.naturalHeight)) {
|
||||
isLoaded.current = true;
|
||||
onLoad();
|
||||
}
|
||||
};
|
||||
const srcAndOnload = isError && fallback ? {
|
||||
src: fallback
|
||||
} : {
|
||||
onLoad,
|
||||
src
|
||||
};
|
||||
return [getImgRef, srcAndOnload, status];
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import type React from 'react';
|
||||
import type { DispatchZoomChangeFunc, TransformType, UpdateTransformFunc } from './useImageTransform';
|
||||
export default function useTouchEvent(imgRef: React.MutableRefObject<HTMLImageElement>, movable: boolean, open: boolean, minScale: number, transform: TransformType, updateTransform: UpdateTransformFunc, dispatchZoomChange: DispatchZoomChangeFunc): {
|
||||
isTouching: boolean;
|
||||
onTouchStart: (event: React.TouchEvent<HTMLImageElement>) => void;
|
||||
onTouchMove: (event: React.TouchEvent<HTMLImageElement>) => void;
|
||||
onTouchEnd: () => void;
|
||||
};
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useTouchEvent;
|
||||
var _react = require("react");
|
||||
var _getFixScaleEleTransPosition = _interopRequireDefault(require("../getFixScaleEleTransPosition"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
function getDistance(a, b) {
|
||||
const x = a.x - b.x;
|
||||
const y = a.y - b.y;
|
||||
return Math.hypot(x, y);
|
||||
}
|
||||
function getCenter(oldPoint1, oldPoint2, newPoint1, newPoint2) {
|
||||
// Calculate the distance each point has moved
|
||||
const distance1 = getDistance(oldPoint1, newPoint1);
|
||||
const distance2 = getDistance(oldPoint2, newPoint2);
|
||||
|
||||
// If both distances are 0, return the original points
|
||||
if (distance1 === 0 && distance2 === 0) {
|
||||
return [oldPoint1.x, oldPoint1.y];
|
||||
}
|
||||
|
||||
// Calculate the ratio of the distances
|
||||
const ratio = distance1 / (distance1 + distance2);
|
||||
|
||||
// Calculate the new center point based on the ratio
|
||||
const x = oldPoint1.x + ratio * (oldPoint2.x - oldPoint1.x);
|
||||
const y = oldPoint1.y + ratio * (oldPoint2.y - oldPoint1.y);
|
||||
return [x, y];
|
||||
}
|
||||
function useTouchEvent(imgRef, movable, open, minScale, transform, updateTransform, dispatchZoomChange) {
|
||||
const {
|
||||
rotate,
|
||||
scale,
|
||||
x,
|
||||
y
|
||||
} = transform;
|
||||
const [isTouching, setIsTouching] = (0, _react.useState)(false);
|
||||
const touchPointInfo = (0, _react.useRef)({
|
||||
point1: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
point2: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
eventType: 'none'
|
||||
});
|
||||
const updateTouchPointInfo = values => {
|
||||
touchPointInfo.current = {
|
||||
...touchPointInfo.current,
|
||||
...values
|
||||
};
|
||||
};
|
||||
const onTouchStart = event => {
|
||||
if (!movable) return;
|
||||
event.stopPropagation();
|
||||
setIsTouching(true);
|
||||
const {
|
||||
touches = []
|
||||
} = event;
|
||||
if (touches.length > 1) {
|
||||
// touch zoom
|
||||
updateTouchPointInfo({
|
||||
point1: {
|
||||
x: touches[0].clientX,
|
||||
y: touches[0].clientY
|
||||
},
|
||||
point2: {
|
||||
x: touches[1].clientX,
|
||||
y: touches[1].clientY
|
||||
},
|
||||
eventType: 'touchZoom'
|
||||
});
|
||||
} else {
|
||||
// touch move
|
||||
updateTouchPointInfo({
|
||||
point1: {
|
||||
x: touches[0].clientX - x,
|
||||
y: touches[0].clientY - y
|
||||
},
|
||||
eventType: 'move'
|
||||
});
|
||||
}
|
||||
};
|
||||
const onTouchMove = event => {
|
||||
const {
|
||||
touches = []
|
||||
} = event;
|
||||
const {
|
||||
point1,
|
||||
point2,
|
||||
eventType
|
||||
} = touchPointInfo.current;
|
||||
if (touches.length > 1 && eventType === 'touchZoom') {
|
||||
// touch zoom
|
||||
const newPoint1 = {
|
||||
x: touches[0].clientX,
|
||||
y: touches[0].clientY
|
||||
};
|
||||
const newPoint2 = {
|
||||
x: touches[1].clientX,
|
||||
y: touches[1].clientY
|
||||
};
|
||||
const [centerX, centerY] = getCenter(point1, point2, newPoint1, newPoint2);
|
||||
const ratio = getDistance(newPoint1, newPoint2) / getDistance(point1, point2);
|
||||
dispatchZoomChange(ratio, 'touchZoom', centerX, centerY, true);
|
||||
updateTouchPointInfo({
|
||||
point1: newPoint1,
|
||||
point2: newPoint2,
|
||||
eventType: 'touchZoom'
|
||||
});
|
||||
} else if (eventType === 'move') {
|
||||
// touch move
|
||||
updateTransform({
|
||||
x: touches[0].clientX - point1.x,
|
||||
y: touches[0].clientY - point1.y
|
||||
}, 'move');
|
||||
updateTouchPointInfo({
|
||||
eventType: 'move'
|
||||
});
|
||||
}
|
||||
};
|
||||
const onTouchEnd = () => {
|
||||
if (!open) return;
|
||||
if (isTouching) {
|
||||
setIsTouching(false);
|
||||
}
|
||||
updateTouchPointInfo({
|
||||
eventType: 'none'
|
||||
});
|
||||
if (minScale > scale) {
|
||||
/** When the scaling ratio is less than the minimum scaling ratio, reset the scaling ratio */
|
||||
return updateTransform({
|
||||
x: 0,
|
||||
y: 0,
|
||||
scale: minScale
|
||||
}, 'touchZoom');
|
||||
}
|
||||
const width = imgRef.current.offsetWidth * scale;
|
||||
const height = imgRef.current.offsetHeight * scale;
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const {
|
||||
left,
|
||||
top
|
||||
} = imgRef.current.getBoundingClientRect();
|
||||
const isRotate = rotate % 180 !== 0;
|
||||
const fixState = (0, _getFixScaleEleTransPosition.default)(isRotate ? height : width, isRotate ? width : height, left, top);
|
||||
if (fixState) {
|
||||
updateTransform({
|
||||
...fixState
|
||||
}, 'dragRebound');
|
||||
}
|
||||
};
|
||||
(0, _react.useEffect)(() => {
|
||||
const preventDefault = e => {
|
||||
e.preventDefault();
|
||||
};
|
||||
if (open && movable) {
|
||||
window.addEventListener('touchmove', preventDefault, {
|
||||
passive: false
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('touchmove', preventDefault);
|
||||
};
|
||||
}, [open, movable]);
|
||||
return {
|
||||
isTouching,
|
||||
onTouchStart,
|
||||
onTouchMove,
|
||||
onTouchEnd
|
||||
};
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import Image from './Image';
|
||||
export * from './Image';
|
||||
export default Image;
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var _exportNames = {};
|
||||
exports.default = void 0;
|
||||
var _Image = _interopRequireWildcard(require("./Image"));
|
||||
Object.keys(_Image).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
||||
if (key in exports && exports[key] === _Image[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _Image[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
||||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
||||
var _default = exports.default = _Image.default;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/// <reference types="react" />
|
||||
/**
|
||||
* Used for PreviewGroup passed image data
|
||||
*/
|
||||
export type ImageElementProps = Pick<React.ImgHTMLAttributes<HTMLImageElement>, 'src' | 'crossOrigin' | 'decoding' | 'draggable' | 'loading' | 'referrerPolicy' | 'sizes' | 'srcSet' | 'useMap' | 'alt' | 'fetchPriority'>;
|
||||
export type PreviewImageElementProps = {
|
||||
data: ImageElementProps;
|
||||
canPreview: boolean;
|
||||
};
|
||||
export type InternalItem = PreviewImageElementProps & {
|
||||
id?: string;
|
||||
};
|
||||
export type RegisterImage = (id: string, data: PreviewImageElementProps) => VoidFunction;
|
||||
export type OnGroupPreview = (id: string, imageSrc: string, mouseX: number, mouseY: number) => void;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/** Scale the ratio base */
|
||||
export declare const BASE_SCALE_RATIO = 1;
|
||||
/** The maximum zoom ratio when the mouse zooms in, adjustable */
|
||||
export declare const WHEEL_MAX_SCALE_RATIO = 1;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.WHEEL_MAX_SCALE_RATIO = exports.BASE_SCALE_RATIO = void 0;
|
||||
/** Scale the ratio base */
|
||||
const BASE_SCALE_RATIO = exports.BASE_SCALE_RATIO = 1;
|
||||
/** The maximum zoom ratio when the mouse zooms in, adjustable */
|
||||
const WHEEL_MAX_SCALE_RATIO = exports.WHEEL_MAX_SCALE_RATIO = 1;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
export declare function isImageValid(src: string): Promise<unknown>;
|
||||
export declare function getClientSize(): {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getClientSize = getClientSize;
|
||||
exports.isImageValid = isImageValid;
|
||||
function isImageValid(src) {
|
||||
return new Promise(resolve => {
|
||||
if (!src) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
const img = document.createElement('img');
|
||||
img.onerror = () => resolve(false);
|
||||
img.onload = () => resolve(true);
|
||||
img.src = src;
|
||||
});
|
||||
}
|
||||
|
||||
// ============================= Legacy =============================
|
||||
function getClientSize() {
|
||||
const width = document.documentElement.clientWidth;
|
||||
const height = window.innerHeight || document.documentElement.clientHeight;
|
||||
return {
|
||||
width,
|
||||
height
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user