tdesign-react
Version:
TDesign Component for React
609 lines (604 loc) • 23.8 kB
JavaScript
/**
* tdesign v1.15.1
* (c) 2025 tdesign
* @license MIT
*/
import { _ as _objectWithoutProperties } from './dep-6b660ef0.js';
import { _ as _defineProperty } from './dep-cb0a3966.js';
import { _ as _asyncToGenerator, r as regenerator } from './dep-52ff3837.js';
import { _ as _slicedToArray } from './dep-48805ab8.js';
import React, { useRef, useState, useMemo, useEffect, useCallback } from 'react';
import classNames from 'classnames';
import { isFunction, isArray } from 'lodash-es';
import { MirrorIcon, RotationIcon, ImageIcon, ImageErrorIcon } from 'tdesign-icons-react';
import { l as largeNumberToFixed } from './dep-76b39920.js';
import useConfig from '../hooks/useConfig.js';
import useGlobalIcon from '../hooks/useGlobalIcon.js';
import { useImagePreviewUrl } from '../hooks/useImagePreviewUrl.js';
import { Image } from '../image/index.js';
import { useLocaleReceiver } from '../locale/LocalReceiver.js';
import { TooltipLite } from '../tooltip/index.js';
import { Dialog } from '../dialog/index.js';
import useIconMap from '../image-viewer/hooks/useIconMap.js';
import useIndex from '../image-viewer/hooks/useIndex.js';
import useMirror from '../image-viewer/hooks/useMirror.js';
import usePosition from '../image-viewer/hooks/usePosition.js';
import useRotate from '../image-viewer/hooks/useRotate.js';
import useScale from '../image-viewer/hooks/useScale.js';
import { downloadFile } from '../image-viewer/utils.js';
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var ImageModalMiniContent = function ImageModalMiniContent(props) {
var _useConfig = useConfig(),
classPrefix = _useConfig.classPrefix;
return /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer-mini__content")
}, /* @__PURE__ */React.createElement(ImageModalItem, {
rotateZ: props.rotateZ,
scale: props.scale,
mirror: props.mirror,
src: props.currentImage.mainImage,
preSrc: props.currentImage.thumbnail,
errorText: props.errorText,
imageReferrerpolicy: props.imageReferrerpolicy,
isSvg: props.currentImage.isSvg
}));
};
var ImageModalMini = function ImageModalMini(props) {
var visible = props.visible,
title = props.title,
scale = props.scale,
currentImage = props.currentImage,
draggable = props.draggable,
tipText = props.tipText,
onZoomOut = props.onZoomOut,
onZoom = props.onZoom,
onClose = props.onClose,
onRotate = props.onRotate,
onMirror = props.onMirror,
onReset = props.onReset;
var _useConfig2 = useConfig(),
classPrefix = _useConfig2.classPrefix;
var footer = /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer-mini__footer")
}, /* @__PURE__ */React.createElement(ImageViewerUtils, {
scale: scale,
tipText: tipText,
currentImage: currentImage,
zIndex: props.zIndex + 1,
onZoom: onZoom,
onZoomOut: onZoomOut,
onRotate: onRotate,
onMirror: onMirror,
onReset: onReset
}));
return /* @__PURE__ */React.createElement(Dialog, {
className: "".concat(classPrefix, "-image-viewer__dialog"),
draggable: draggable,
visible: visible,
width: "min(90vw, 1000px)",
placement: "center",
mode: "modeless",
closeOnOverlayClick: false,
cancelBtn: null,
confirmBtn: null,
header: /* @__PURE__ */React.createElement("span", {
className: "".concat(classPrefix, "-image-viewer__dialog-title")
}, title),
footer: footer,
onClose: onClose
}, /* @__PURE__ */React.createElement(ImageModalMiniContent, _objectSpread({}, props)));
};
var _excluded = ["closeOnOverlay", "showOverlay", "zIndex", "images", "isMini", "imageScale", "viewerScale", "closeBtn", "draggable", "visible", "title", "closeOnEscKeydown", "imageReferrerpolicy", "onOpen", "onClose", "onDownload"];
var ImageError = function ImageError(_ref) {
var errorText = _ref.errorText;
var _useConfig = useConfig(),
classPrefix = _useConfig.classPrefix;
var _useGlobalIcon = useGlobalIcon({
ImageErrorIcon: ImageErrorIcon
}),
ImageErrorIcon$1 = _useGlobalIcon.ImageErrorIcon;
return /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__img-error")
}, /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__img-error-content")
}, /* @__PURE__ */React.createElement(ImageErrorIcon$1, {
size: "4em"
}), /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__img-error-text")
}, errorText)));
};
var ImageModalItem = function ImageModalItem(_ref2) {
var rotateZ = _ref2.rotateZ,
scale = _ref2.scale,
src = _ref2.src,
preSrc = _ref2.preSrc,
mirror = _ref2.mirror,
errorText = _ref2.errorText,
imageReferrerpolicy = _ref2.imageReferrerpolicy,
isSvg = _ref2.isSvg;
var _useConfig2 = useConfig(),
classPrefix = _useConfig2.classPrefix;
var imgRef = useRef(null);
var svgRef = useRef(null);
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
loaded = _useState2[0],
setLoaded = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
error = _useState4[0],
setError = _useState4[1];
var imgStyle = {
transform: "rotateZ(".concat(rotateZ, "deg) scale(").concat(scale, ")"),
display: !preSrc || loaded ? "block" : "none"
};
var _useImagePreviewUrl = useImagePreviewUrl(preSrc),
preSrcImagePreviewUrl = _useImagePreviewUrl.previewUrl;
var _useImagePreviewUrl2 = useImagePreviewUrl(src),
mainImagePreviewUrl = _useImagePreviewUrl2.previewUrl;
var displayRef = useMemo(function () {
if (isSvg) return svgRef;
return imgRef;
}, [isSvg]);
var _usePosition = usePosition(displayRef),
position = _usePosition.position;
var preImgStyle = {
transform: "rotateZ(".concat(rotateZ, "deg) scale(").concat(scale, ")"),
display: !loaded ? "block" : "none"
};
var boxStyle = {
transform: "translate(".concat(position[0], "px, ").concat(position[1], "px) scale(").concat(mirror, ", 1)")
};
var createSvgShadow = /*#__PURE__*/function () {
var _ref3 = _asyncToGenerator(/*#__PURE__*/regenerator.mark(function _callee(url) {
var _element$classList;
var response, svgText, element, shadowRoot, container, svgElement, svgViewBox, viewBoxValues, svgViewBoxWidth, svgViewBoxHeight, bbox, calculatedViewBox;
return regenerator.wrap(function (_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.next = 1;
return fetch(url);
case 1:
response = _context.sent;
if (response.ok) {
_context.next = 2;
break;
}
setError(true);
throw new Error("Failed to fetch SVG: ".concat(response.statusText));
case 2:
_context.next = 3;
return response.text();
case 3:
svgText = _context.sent;
element = svgRef.current;
element.innerHTML = "";
(_element$classList = element.classList) === null || _element$classList === void 0 || _element$classList.add("".concat(classPrefix, "-image-viewer__modal-image-svg"));
shadowRoot = element.attachShadow({
mode: "closed"
});
container = document.createElement("div");
container.style.background = "transparent";
container.innerHTML = svgText;
shadowRoot.appendChild(container);
svgElement = container.querySelector("svg");
if (svgElement) {
svgViewBox = svgElement.getAttribute("viewBox");
if (svgViewBox) {
viewBoxValues = svgViewBox.split(/[\s,]/).filter(function (v) {
return v;
}).map(parseFloat);
svgViewBoxWidth = viewBoxValues[2];
svgViewBoxHeight = viewBoxValues[3];
container.style.width = "".concat(svgViewBoxWidth, "px");
container.style.height = "".concat(svgViewBoxHeight, "px");
} else {
bbox = svgElement.getBBox();
calculatedViewBox = "".concat(bbox.x, " ").concat(bbox.y, " ").concat(bbox.width, " ").concat(bbox.height);
svgElement.setAttribute("viewBox", calculatedViewBox);
container.style.width = "".concat(bbox.width, "px");
container.style.height = "".concat(bbox.height, "px");
}
}
setLoaded(true);
case 4:
case "end":
return _context.stop();
}
}, _callee);
}));
return function createSvgShadow(_x) {
return _ref3.apply(this, arguments);
};
}();
useEffect(function () {
setError(false);
}, [preSrcImagePreviewUrl, mainImagePreviewUrl]);
useEffect(function () {
if (isSvg && mainImagePreviewUrl) {
createSvgShadow(mainImagePreviewUrl);
}
}, [mainImagePreviewUrl]);
return /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__modal-pic")
}, /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__modal-box"),
style: boxStyle
}, error && /* @__PURE__ */React.createElement(ImageError, {
errorText: errorText
}), !error && !!preSrc && preSrcImagePreviewUrl && /* @__PURE__ */React.createElement("img", {
className: "".concat(classPrefix, "-image-viewer__modal-image"),
src: preSrcImagePreviewUrl,
style: preImgStyle,
referrerPolicy: imageReferrerpolicy,
alt: "image",
draggable: "false"
}), !error && mainImagePreviewUrl && !isSvg && /* @__PURE__ */React.createElement("img", {
ref: imgRef,
className: "".concat(classPrefix, "-image-viewer__modal-image"),
src: mainImagePreviewUrl,
style: imgStyle,
onLoad: function onLoad() {
return setLoaded(true);
},
onError: function onError() {
return setError(true);
},
referrerPolicy: imageReferrerpolicy,
alt: "image",
draggable: "false"
}), !error && !!mainImagePreviewUrl && isSvg && /* @__PURE__ */React.createElement("div", {
ref: svgRef,
className: "".concat(classPrefix, "-image-viewer__modal-image"),
style: imgStyle,
"data-alt": "svg",
draggable: "false"
})));
};
var ROTATE_COUNT = 90;
var ImageModalIcon = function ImageModalIcon(_ref4) {
var onClick = _ref4.onClick,
className = _ref4.className,
disabled = _ref4.disabled,
isRange = _ref4.isRange,
name = _ref4.name,
label = _ref4.label,
_ref4$size = _ref4.size,
size = _ref4$size === void 0 ? "16px" : _ref4$size;
var _useConfig3 = useConfig(),
classPrefix = _useConfig3.classPrefix;
var Icons = useIconMap();
var Icon = Icons[name];
return /* @__PURE__ */React.createElement("div", {
className: classNames("".concat(classPrefix, "-image-viewer__modal-icon"), className, _defineProperty({}, "".concat(classPrefix, "-is-disabled"), disabled)),
onClick: onClick
}, name && /* @__PURE__ */React.createElement(Icon, {
size: size,
className: isRange ? "is-range" : null
}), label && /* @__PURE__ */React.createElement("span", {
className: "".concat(classPrefix, "-image-viewer__modal-icon-label")
}, label));
};
var ImageViewerUtils = function ImageViewerUtils(_ref5) {
var scale = _ref5.scale,
currentImage = _ref5.currentImage,
tipText = _ref5.tipText,
zIndex = _ref5.zIndex,
onMirror = _ref5.onMirror,
onRotate = _ref5.onRotate,
onZoom = _ref5.onZoom,
onZoomOut = _ref5.onZoomOut,
onReset = _ref5.onReset,
onDownload = _ref5.onDownload;
var _useConfig4 = useConfig(),
classPrefix = _useConfig4.classPrefix;
var _useGlobalIcon2 = useGlobalIcon({
MirrorIcon: MirrorIcon,
RotationIcon: RotationIcon,
ImageIcon: ImageIcon
}),
MirrorIcon$1 = _useGlobalIcon2.MirrorIcon,
RotationIcon$1 = _useGlobalIcon2.RotationIcon,
ImageIcon$1 = _useGlobalIcon2.ImageIcon;
return /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__utils")
}, /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__utils-content")
}, /* @__PURE__ */React.createElement(TooltipLite, {
className: "".concat(classPrefix, "-image-viewer__utils--tip"),
content: tipText.mirror,
showShadow: false,
zIndex: zIndex
}, /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__modal-icon"),
onClick: onMirror
}, /* @__PURE__ */React.createElement(MirrorIcon$1, {
size: "medium"
}))), /* @__PURE__ */React.createElement(TooltipLite, {
className: "".concat(classPrefix, "-image-viewer__utils--tip"),
content: tipText.rotate,
showShadow: false,
zIndex: zIndex
}, /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__modal-icon"),
onClick: function onClick() {
return onRotate(-ROTATE_COUNT);
}
}, /* @__PURE__ */React.createElement(RotationIcon$1, {
size: "medium"
}))), /* @__PURE__ */React.createElement(ImageModalIcon, {
size: "medium",
name: "zoom-out",
onClick: onZoomOut
}), /* @__PURE__ */React.createElement(ImageModalIcon, {
className: "".concat(classPrefix, "-image-viewer__utils-scale"),
size: "medium",
label: "".concat(largeNumberToFixed(String(scale * 100)), "%")
}), /* @__PURE__ */React.createElement(ImageModalIcon, {
size: "medium",
name: "zoom-in",
onClick: onZoom
}), /* @__PURE__ */React.createElement(TooltipLite, {
className: "".concat(classPrefix, "-image-viewer__utils--tip"),
content: tipText.originalSize,
showShadow: false,
zIndex: zIndex
}, /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__modal-icon"),
onClick: onReset
}, /* @__PURE__ */React.createElement(ImageIcon$1, {
size: "medium",
name: "image"
}))), currentImage.download && /* @__PURE__ */React.createElement(ImageModalIcon, {
size: "medium",
name: "download",
onClick: function onClick() {
if (isFunction(onDownload)) {
onDownload(currentImage.mainImage);
return;
}
downloadFile(currentImage.mainImage);
}
})));
};
function OneImagePreview(_ref6) {
var image = _ref6.image,
classPrefix = _ref6.classPrefix,
imageReferrerpolicy = _ref6.imageReferrerpolicy;
var _useImagePreviewUrl3 = useImagePreviewUrl(image.thumbnail || image.mainImage),
previewUrl = _useImagePreviewUrl3.previewUrl;
return /* @__PURE__ */React.createElement(Image, {
alt: "",
error: "",
src: previewUrl,
className: "".concat(classPrefix, "-image-viewer__header-img"),
referrerpolicy: imageReferrerpolicy
});
}
var ImageViewerHeader = function ImageViewerHeader(props) {
var _useConfig5 = useConfig(),
classPrefix = _useConfig5.classPrefix;
var images = props.images,
currentIndex = props.currentIndex,
onImgClick = props.onImgClick,
imageReferrerpolicy = props.imageReferrerpolicy;
var _useState5 = useState(true),
_useState6 = _slicedToArray(_useState5, 2),
isExpand = _useState6[0],
setIsExpand = _useState6[1];
var transStyle = {
transform: "translateX(calc(-".concat(currentIndex, " * (40px / 9 * 16 + 4px)))")
};
return /* @__PURE__ */React.createElement("div", {
className: classNames("".concat(classPrefix, "-image-viewer__modal-header"), _defineProperty({}, "".concat(classPrefix, "-is-show"), isExpand))
}, /* @__PURE__ */React.createElement(ImageModalIcon, {
name: "chevron-down",
className: "".concat(classPrefix, "-image-viewer__header-pre-bt"),
onClick: function onClick() {
return setIsExpand(!isExpand);
}
}), /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__header-prev")
}, /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__header-trans"),
style: transStyle
}, images.map(function (image, index) {
return /* @__PURE__ */React.createElement("div", {
key: index,
className: classNames("".concat(classPrefix, "-image-viewer__header-box"), _defineProperty({}, "".concat(classPrefix, "-is-active"), index === currentIndex)),
onClick: function onClick() {
return onImgClick(index, {
trigger: "current"
});
}
}, /* @__PURE__ */React.createElement(OneImagePreview, {
image: image,
classPrefix: classPrefix,
imageReferrerpolicy: imageReferrerpolicy
}));
}))));
};
var ImageModal = function ImageModal(props) {
var closeOnOverlay = props.closeOnOverlay,
_props$showOverlay = props.showOverlay,
showOverlay = _props$showOverlay === void 0 ? true : _props$showOverlay,
zIndex = props.zIndex,
images = props.images,
isMini = props.isMini,
imageScale = props.imageScale,
viewerScale = props.viewerScale,
closeBtn = props.closeBtn,
draggable = props.draggable,
visible = props.visible,
title = props.title,
closeOnEscKeydown = props.closeOnEscKeydown,
imageReferrerpolicy = props.imageReferrerpolicy,
onOpen = props.onOpen,
onClose = props.onClose,
onDownload = props.onDownload,
resProps = _objectWithoutProperties(props, _excluded);
var _useConfig6 = useConfig(),
classPrefix = _useConfig6.classPrefix;
var _useLocaleReceiver = useLocaleReceiver("imageViewer"),
_useLocaleReceiver2 = _slicedToArray(_useLocaleReceiver, 2),
locale = _useLocaleReceiver2[0],
t = _useLocaleReceiver2[1];
if (resProps.index === void 0) delete resProps.index;
var _useIndex = useIndex(resProps, images),
index = _useIndex.index,
next = _useIndex.next,
prev = _useIndex.prev,
setIndex = _useIndex.setIndex;
var _useRotate = useRotate(),
rotateZ = _useRotate.rotateZ,
onResetRotate = _useRotate.onResetRotate,
onRotate = _useRotate.onRotate;
var _useScale = useScale(imageScale, visible),
scale = _useScale.scale,
onZoom = _useScale.onZoom,
onZoomOut = _useScale.onZoomOut,
onResetScale = _useScale.onResetScale;
var _useMirror = useMirror(),
mirror = _useMirror.mirror,
onResetMirror = _useMirror.onResetMirror,
onMirror = _useMirror.onMirror;
var onReset = useCallback(function () {
onResetScale();
onResetRotate();
onResetMirror();
}, [onResetMirror, onResetScale, onResetRotate]);
var onKeyDown = useCallback(function (event) {
switch (event.key) {
case "ArrowRight":
return next();
case "ArrowLeft":
return prev();
case "ArrowUp":
return onZoom();
case "ArrowDown":
return onZoomOut();
case "Escape":
return closeOnEscKeydown && (onClose === null || onClose === void 0 ? void 0 : onClose({
trigger: "esc",
e: event
}));
}
}, [next, onClose, prev, onZoom, onZoomOut, closeOnEscKeydown]);
useEffect(function () {
document.addEventListener("keydown", onKeyDown);
return function () {
return document.removeEventListener("keydown", onKeyDown);
};
}, [onKeyDown]);
useEffect(function () {
onReset();
}, [index, onReset]);
if (!isArray(images) || images.length < 1) return null;
var currentImage = images[index];
var tipText = {
mirror: t(locale.mirrorTipText),
rotate: t(locale.rotateTipText),
originalSize: t(locale.originalSizeTipText)
};
var errorText = t(locale.errorText);
if (isMini) {
return /* @__PURE__ */React.createElement(ImageModalMini, {
visible: visible,
draggable: draggable,
index: index,
images: images,
imageScale: imageScale,
viewerScale: viewerScale,
rotateZ: rotateZ,
zIndex: zIndex,
currentImage: currentImage,
mirror: mirror,
scale: scale,
title: title,
errorText: errorText,
tipText: tipText,
imageReferrerpolicy: imageReferrerpolicy,
prev: prev,
next: next,
onMirror: onMirror,
onRotate: onRotate,
onZoom: onZoom,
onZoomOut: onZoomOut,
onReset: onReset,
onClose: onClose
});
}
var closeNode = closeBtn;
if (closeBtn === true) {
closeNode = /* @__PURE__ */React.createElement(ImageModalIcon, {
name: "close",
size: "24px",
className: "".concat(classPrefix, "-image-viewer__modal-close-bt "),
onClick: function onClick(e) {
return onClose && onClose({
trigger: "close-btn",
e: e
});
}
});
} else if (isFunction(closeBtn)) closeNode = closeBtn({
onClose: onClose,
onOpen: onOpen
});
return /* @__PURE__ */React.createElement("div", {
className: classNames("".concat(classPrefix, "-image-viewer-preview-image"), _defineProperty({}, "".concat(classPrefix, "-is-hide"), !visible)),
style: {
zIndex: zIndex
}
}, !!showOverlay && /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__modal-mask"),
onClick: function onClick(e) {
return closeOnOverlay && (onClose === null || onClose === void 0 ? void 0 : onClose({
trigger: "overlay",
e: e
}));
}
}), images.length > 1 && /* @__PURE__ */React.createElement(React.Fragment, null, /* @__PURE__ */React.createElement(ImageViewerHeader, {
images: images,
currentIndex: index,
onImgClick: setIndex,
imageReferrerpolicy: imageReferrerpolicy
}), /* @__PURE__ */React.createElement("div", {
className: "".concat(classPrefix, "-image-viewer__modal-index")
}, /* @__PURE__ */React.createElement("span", null, title), "".concat(index + 1, "/").concat(images.length)), /* @__PURE__ */React.createElement(ImageModalIcon, {
size: "24px",
name: "chevron-left",
className: "".concat(classPrefix, "-image-viewer__modal-prev-bt"),
onClick: prev,
disabled: index <= 0
}), /* @__PURE__ */React.createElement(ImageModalIcon, {
size: "24px",
name: "chevron-right",
className: "".concat(classPrefix, "-image-viewer__modal-next-bt"),
onClick: next,
disabled: index >= images.length - 1
})), /* @__PURE__ */React.createElement(ImageViewerUtils, {
scale: scale,
tipText: tipText,
currentImage: currentImage,
zIndex: zIndex + 1,
onZoom: onZoom,
onZoomOut: onZoomOut,
onDownload: onDownload,
onRotate: onRotate,
onMirror: onMirror,
onReset: onReset
}), closeNode, /* @__PURE__ */React.createElement(ImageModalItem, {
scale: scale,
rotateZ: rotateZ,
mirror: mirror,
preSrc: currentImage.thumbnail,
src: currentImage.mainImage,
errorText: errorText,
imageReferrerpolicy: imageReferrerpolicy,
isSvg: currentImage.isSvg
}));
};
export { ImageModal as I, ImageModalMiniContent as a, ImageModalMini as b, ImageModalItem as c, ImageViewerUtils as d };
//# sourceMappingURL=dep-6a010af7.js.map