@lobehub/ui 5.24.0 → 5.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/A/index.mjs +2 -1
- package/es/A/index.mjs.map +1 -1
- package/es/Accordion/AccordionItem.mjs +0 -1
- package/es/Accordion/AccordionItem.mjs.map +1 -1
- package/es/ActionIcon/components/utils.mjs +7 -9
- package/es/ActionIcon/components/utils.mjs.map +1 -1
- package/es/Checkbox/CheckboxGroup.mjs +4 -2
- package/es/Checkbox/CheckboxGroup.mjs.map +1 -1
- package/es/CodeDiff/CodeDiff.mjs +20 -18
- package/es/CodeDiff/CodeDiff.mjs.map +1 -1
- package/es/CodeDiff/PatchDiff.mjs +18 -16
- package/es/CodeDiff/PatchDiff.mjs.map +1 -1
- package/es/CopyButton/CopyButton.mjs +2 -1
- package/es/CopyButton/CopyButton.mjs.map +1 -1
- package/es/Highlighter/LangSelect.mjs +41 -40
- package/es/Highlighter/LangSelect.mjs.map +1 -1
- package/es/Highlighter/SyntaxHighlighter/StaticRenderer.mjs +2 -1
- package/es/Highlighter/SyntaxHighlighter/StaticRenderer.mjs.map +1 -1
- package/es/HotkeyInput/HotkeyInput.mjs +3 -1
- package/es/HotkeyInput/HotkeyInput.mjs.map +1 -1
- package/es/HtmlPreview/const.mjs +1 -1
- package/es/HtmlPreview/const.mjs.map +1 -1
- package/es/Icon/components/utils.mjs +7 -9
- package/es/Icon/components/utils.mjs.map +1 -1
- package/es/Image/Image.mjs +138 -37
- package/es/Image/Image.mjs.map +1 -1
- package/es/Image/PreviewGroup.d.mts +1 -0
- package/es/Image/PreviewGroup.mjs +33 -10
- package/es/Image/PreviewGroup.mjs.map +1 -1
- package/es/Image/index.d.mts +2 -2
- package/es/Image/index.mjs +1 -1
- package/es/Image/style.mjs +126 -71
- package/es/Image/style.mjs.map +1 -1
- package/es/Image/type.d.mts +14 -17
- package/es/Image/viewer/GalleryNav.mjs +44 -0
- package/es/Image/viewer/GalleryNav.mjs.map +1 -0
- package/es/Image/viewer/ImageViewer.mjs +275 -0
- package/es/Image/viewer/ImageViewer.mjs.map +1 -0
- package/es/Image/viewer/PreviewOutlet.mjs +19 -0
- package/es/Image/viewer/PreviewOutlet.mjs.map +1 -0
- package/es/Image/viewer/Toolbar.mjs +184 -0
- package/es/Image/viewer/Toolbar.mjs.map +1 -0
- package/es/Image/viewer/ViewerChrome.mjs +54 -0
- package/es/Image/viewer/ViewerChrome.mjs.map +1 -0
- package/es/Image/viewer/geometry.mjs +85 -0
- package/es/Image/viewer/geometry.mjs.map +1 -0
- package/es/Image/viewer/registry.d.mts +2 -0
- package/es/Image/viewer/registry.mjs +52 -0
- package/es/Image/viewer/registry.mjs.map +1 -0
- package/es/Image/viewer/useChromeIdle.mjs +72 -0
- package/es/Image/viewer/useChromeIdle.mjs.map +1 -0
- package/es/Image/viewer/useFinalFocus.mjs +10 -0
- package/es/Image/viewer/useFinalFocus.mjs.map +1 -0
- package/es/Image/viewer/useFlipTransition.mjs +321 -0
- package/es/Image/viewer/useFlipTransition.mjs.map +1 -0
- package/es/Image/viewer/useGalleryNav.mjs +89 -0
- package/es/Image/viewer/useGalleryNav.mjs.map +1 -0
- package/es/Image/viewer/useRefitTransition.mjs +47 -0
- package/es/Image/viewer/useRefitTransition.mjs.map +1 -0
- package/es/Image/viewer/useViewerGestures.mjs +148 -0
- package/es/Image/viewer/useViewerGestures.mjs.map +1 -0
- package/es/Image/viewer/useZoomPan.mjs +346 -0
- package/es/Image/viewer/useZoomPan.mjs.map +1 -0
- package/es/Img/index.mjs +2 -1
- package/es/Img/index.mjs.map +1 -1
- package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs +2 -1
- package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs.map +1 -1
- package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs +2 -2
- package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs.map +1 -1
- package/es/Modal/RawModalStackItem.mjs +6 -5
- package/es/Modal/RawModalStackItem.mjs.map +1 -1
- package/es/Modal/imperative.mjs +4 -2
- package/es/Modal/imperative.mjs.map +1 -1
- package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs +1 -1
- package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs.map +1 -1
- package/es/ScrollShadow/ScrollShadow.mjs +13 -12
- package/es/ScrollShadow/ScrollShadow.mjs.map +1 -1
- package/es/Skeleton/SkeletonButton.mjs +2 -1
- package/es/Skeleton/SkeletonButton.mjs.map +1 -1
- package/es/SortableList/SortableList.mjs +5 -1
- package/es/SortableList/SortableList.mjs.map +1 -1
- package/es/Text/Text.mjs +22 -21
- package/es/Text/Text.mjs.map +1 -1
- package/es/ThemeProvider/ThemeProvider.mjs +3 -2
- package/es/ThemeProvider/ThemeProvider.mjs.map +1 -1
- package/es/awesome/GradientButton/GradientButton.mjs +1 -3
- package/es/awesome/GradientButton/GradientButton.mjs.map +1 -1
- package/es/awesome/Spotlight/Spotlight.mjs +2 -1
- package/es/awesome/Spotlight/Spotlight.mjs.map +1 -1
- package/es/base-ui/Button/Button.mjs +13 -11
- package/es/base-ui/Button/Button.mjs.map +1 -1
- package/es/base-ui/Button/SplitButton.mjs +2 -1
- package/es/base-ui/Button/SplitButton.mjs.map +1 -1
- package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs +2 -1
- package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs.map +1 -1
- package/es/base-ui/ContextMenu/renderItems.mjs +2 -1
- package/es/base-ui/ContextMenu/renderItems.mjs.map +1 -1
- package/es/base-ui/Drawer/Drawer.d.mts +6 -0
- package/es/base-ui/Drawer/Drawer.mjs +152 -0
- package/es/base-ui/Drawer/Drawer.mjs.map +1 -0
- package/es/base-ui/Drawer/DrawerLayerContext.mjs +10 -0
- package/es/base-ui/Drawer/DrawerLayerContext.mjs.map +1 -0
- package/es/base-ui/Drawer/DrawerPushContext.mjs +27 -0
- package/es/base-ui/Drawer/DrawerPushContext.mjs.map +1 -0
- package/es/base-ui/Drawer/atoms.d.mts +58 -0
- package/es/base-ui/Drawer/atoms.mjs +262 -0
- package/es/base-ui/Drawer/atoms.mjs.map +1 -0
- package/es/base-ui/Drawer/constants.d.mts +17 -0
- package/es/base-ui/Drawer/constants.mjs +72 -0
- package/es/base-ui/Drawer/constants.mjs.map +1 -0
- package/es/base-ui/Drawer/index.d.mts +5 -0
- package/es/base-ui/Drawer/style.mjs +295 -0
- package/es/base-ui/Drawer/style.mjs.map +1 -0
- package/es/base-ui/Drawer/type.d.mts +65 -0
- package/es/base-ui/DropdownMenu/DropdownMenu.mjs +2 -1
- package/es/base-ui/DropdownMenu/DropdownMenu.mjs.map +1 -1
- package/es/base-ui/DropdownMenu/atoms.mjs +2 -1
- package/es/base-ui/DropdownMenu/atoms.mjs.map +1 -1
- package/es/base-ui/DropdownMenu/renderItems.mjs +2 -1
- package/es/base-ui/DropdownMenu/renderItems.mjs.map +1 -1
- package/es/base-ui/FloatingSheet/FloatingSheet.mjs +4 -1
- package/es/base-ui/FloatingSheet/FloatingSheet.mjs.map +1 -1
- package/es/base-ui/Input/style.d.mts +1 -1
- package/es/base-ui/Modal/atoms.mjs +7 -5
- package/es/base-ui/Modal/atoms.mjs.map +1 -1
- package/es/base-ui/Modal/imperative.mjs +2 -1
- package/es/base-ui/Modal/imperative.mjs.map +1 -1
- package/es/base-ui/Popover/atoms.mjs +2 -1
- package/es/base-ui/Popover/atoms.mjs.map +1 -1
- package/es/base-ui/Popover/context.mjs +4 -2
- package/es/base-ui/Popover/context.mjs.map +1 -1
- package/es/base-ui/Select/atoms.mjs +2 -1
- package/es/base-ui/Select/atoms.mjs.map +1 -1
- package/es/base-ui/Toast/hostGuard.mjs +26 -0
- package/es/base-ui/Toast/hostGuard.mjs.map +1 -0
- package/es/base-ui/Toast/imperative.mjs +43 -20
- package/es/base-ui/Toast/imperative.mjs.map +1 -1
- package/es/base-ui/Toast/pendingQueue.mjs +30 -0
- package/es/base-ui/Toast/pendingQueue.mjs.map +1 -0
- package/es/base-ui/index.d.mts +6 -1
- package/es/base-ui/index.mjs +5 -2
- package/es/brand/LobeChat/index.mjs +0 -1
- package/es/brand/LobeChat/index.mjs.map +1 -1
- package/es/brand/LobeHub/index.mjs +0 -1
- package/es/brand/LobeHub/index.mjs.map +1 -1
- package/es/brand/Logo3d/index.mjs +2 -1
- package/es/brand/Logo3d/index.mjs.map +1 -1
- package/es/chat/ChatItem/components/Actions.mjs +5 -4
- package/es/chat/ChatItem/components/Actions.mjs.map +1 -1
- package/es/chat/ChatList/ChatList.mjs +2 -1
- package/es/chat/ChatList/ChatList.mjs.map +1 -1
- package/es/color/ColorScales/ScaleRow.mjs +0 -2
- package/es/color/ColorScales/ScaleRow.mjs.map +1 -1
- package/es/hooks/useMermaid.mjs +2 -1
- package/es/hooks/useMermaid.mjs.map +1 -1
- package/es/i18n/resources/en/image.d.mts +5 -0
- package/es/i18n/resources/en/image.mjs +6 -1
- package/es/i18n/resources/en/image.mjs.map +1 -1
- package/es/i18n/resources/zhCn/image.d.mts +5 -0
- package/es/i18n/resources/zhCn/image.mjs +6 -1
- package/es/i18n/resources/zhCn/image.mjs.map +1 -1
- package/es/index.mjs +8 -8
- package/package.json +1 -1
- package/es/Image/components/Preview.mjs +0 -23
- package/es/Image/components/Preview.mjs.map +0 -1
- package/es/Image/components/Toolbar.mjs +0 -128
- package/es/Image/components/Toolbar.mjs.map +0 -1
- package/es/Image/components/usePreview.mjs +0 -58
- package/es/Image/components/usePreview.mjs.map +0 -1
- package/es/Image/components/usePreviewGroup.mjs +0 -57
- package/es/Image/components/usePreviewGroup.mjs.map +0 -1
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { memo, useEffect, useRef } from "react";
|
|
3
|
-
import { jsx } from "react/jsx-runtime";
|
|
4
|
-
//#region src/Image/components/Preview.tsx
|
|
5
|
-
const Preview = memo(({ children, visible }) => {
|
|
6
|
-
const ref = useRef(null);
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
if (!ref.current) return;
|
|
9
|
-
const handleDisableZoom = (event) => {
|
|
10
|
-
event.preventDefault();
|
|
11
|
-
};
|
|
12
|
-
if (visible) ref.current.addEventListener("wheel", handleDisableZoom, { passive: false });
|
|
13
|
-
else ref.current.removeEventListener("wheel", handleDisableZoom);
|
|
14
|
-
}, [visible]);
|
|
15
|
-
return /* @__PURE__ */ jsx("div", {
|
|
16
|
-
ref,
|
|
17
|
-
children
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
//#endregion
|
|
21
|
-
export { Preview as default };
|
|
22
|
-
|
|
23
|
-
//# sourceMappingURL=Preview.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Preview.mjs","names":[],"sources":["../../../src/Image/components/Preview.tsx"],"sourcesContent":["'use client';\n\nimport { memo, type PropsWithChildren, useEffect, useRef } from 'react';\n\ninterface PreviewProps extends PropsWithChildren {\n visible?: boolean;\n}\n\nconst Preview = memo<PreviewProps>(({ children, visible }) => {\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (!ref.current) return;\n\n const handleDisableZoom = (event: any) => {\n event.preventDefault();\n };\n\n if (visible) {\n ref.current.addEventListener('wheel', handleDisableZoom, { passive: false });\n } else {\n ref.current.removeEventListener('wheel', handleDisableZoom);\n }\n }, [visible]);\n\n return <div ref={ref}>{children}</div>;\n});\n\nexport default Preview;\n"],"mappings":";;;;AAQA,MAAM,UAAU,MAAoB,EAAE,UAAU,cAAc;CAC5D,MAAM,MAAM,OAAuB,IAAI;CACvC,gBAAgB;EACd,IAAI,CAAC,IAAI,SAAS;EAElB,MAAM,qBAAqB,UAAe;GACxC,MAAM,eAAe;EACvB;EAEA,IAAI,SACF,IAAI,QAAQ,iBAAiB,SAAS,mBAAmB,EAAE,SAAS,MAAM,CAAC;OAE3E,IAAI,QAAQ,oBAAoB,SAAS,iBAAiB;CAE9D,GAAG,CAAC,OAAO,CAAC;CAEZ,OAAO,oBAAC,OAAD;EAAU;EAAM;CAAc,CAAA;AACvC,CAAC"}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import FlexBasic_default from "../../Flex/FlexBasic.mjs";
|
|
2
|
-
import TooltipGroup from "../../base-ui/Tooltip/TooltipGroup.mjs";
|
|
3
|
-
import ActionIcon from "../../ActionIcon/ActionIcon.mjs";
|
|
4
|
-
import { useTranslation } from "../../i18n/useTranslation.mjs";
|
|
5
|
-
import { downloadBlob } from "../../utils/downloadBlob.mjs";
|
|
6
|
-
import { styles } from "../style.mjs";
|
|
7
|
-
import image_default from "../../i18n/resources/en/image.mjs";
|
|
8
|
-
import { getClipboardBlob } from "../../utils/blobToPng.mjs";
|
|
9
|
-
import { memo, useCallback, useState } from "react";
|
|
10
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
import { message } from "antd";
|
|
12
|
-
import { Copy, Download, FlipHorizontal, FlipVertical, RotateCcw, RotateCw, ZoomIn, ZoomOut } from "lucide-react";
|
|
13
|
-
//#region src/Image/components/Toolbar.tsx
|
|
14
|
-
const getFileNameFromUrl = (url) => {
|
|
15
|
-
try {
|
|
16
|
-
const match = new URL(url).pathname.match(/\/([^/]+)$/);
|
|
17
|
-
return match ? decodeURIComponent(match[1]) : "image";
|
|
18
|
-
} catch {
|
|
19
|
-
return "image";
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
const getExtensionFromMimeType = (mimeType) => {
|
|
23
|
-
return {
|
|
24
|
-
"image/svg+xml": "svg",
|
|
25
|
-
"image/png": "png",
|
|
26
|
-
"image/jpeg": "jpg",
|
|
27
|
-
"image/jpg": "jpg",
|
|
28
|
-
"image/webp": "webp",
|
|
29
|
-
"image/gif": "gif"
|
|
30
|
-
}[mimeType?.toLowerCase()] || mimeType?.split("/")[1]?.split("+")[0] || "png";
|
|
31
|
-
};
|
|
32
|
-
const Toolbar = memo(({ children, info, minScale, maxScale }) => {
|
|
33
|
-
const { t } = useTranslation(image_default);
|
|
34
|
-
const [containerEl, setContainerEl] = useState(null);
|
|
35
|
-
const [copyLoading, setCopyLoading] = useState(false);
|
|
36
|
-
const [downloadLoading, setDownloadLoading] = useState(false);
|
|
37
|
-
const { transform: { scale }, actions: { onFlipY, onFlipX, onRotateLeft, onRotateRight, onZoomOut, onZoomIn }, image: { url } } = info;
|
|
38
|
-
const handleDownload = useCallback(async () => {
|
|
39
|
-
setDownloadLoading(true);
|
|
40
|
-
try {
|
|
41
|
-
const blob = await (await fetch(url, { mode: "cors" })).blob();
|
|
42
|
-
const blobUrl = URL.createObjectURL(blob);
|
|
43
|
-
let fileName = getFileNameFromUrl(url);
|
|
44
|
-
const ext = getExtensionFromMimeType(blob.type);
|
|
45
|
-
if (!fileName.includes(".")) fileName = `${fileName}.${ext}`;
|
|
46
|
-
else if (fileName.endsWith(".svg+xml")) fileName = fileName.replace(/\.svg\+xml$/i, ".svg");
|
|
47
|
-
await downloadBlob(blobUrl, fileName);
|
|
48
|
-
URL.revokeObjectURL(blobUrl);
|
|
49
|
-
message.success(t("image.downloadSuccess"));
|
|
50
|
-
} catch {
|
|
51
|
-
message.error(t("image.downloadFailed"));
|
|
52
|
-
} finally {
|
|
53
|
-
setDownloadLoading(false);
|
|
54
|
-
}
|
|
55
|
-
}, [url, t]);
|
|
56
|
-
const handleCopy = useCallback(async () => {
|
|
57
|
-
setCopyLoading(true);
|
|
58
|
-
try {
|
|
59
|
-
const clipboardBlob = await getClipboardBlob(await (await fetch(url, { mode: "cors" })).blob());
|
|
60
|
-
await navigator.clipboard.write([new ClipboardItem(clipboardBlob)]);
|
|
61
|
-
message.success(t("image.copySuccess"));
|
|
62
|
-
} catch {
|
|
63
|
-
message.error(t("image.copyFailed"));
|
|
64
|
-
} finally {
|
|
65
|
-
setCopyLoading(false);
|
|
66
|
-
}
|
|
67
|
-
}, [url, t]);
|
|
68
|
-
return /* @__PURE__ */ jsx(TooltipGroup, {
|
|
69
|
-
popupContainer: containerEl ?? void 0,
|
|
70
|
-
children: /* @__PURE__ */ jsxs(FlexBasic_default, {
|
|
71
|
-
horizontal: true,
|
|
72
|
-
className: styles.toolbar,
|
|
73
|
-
gap: 4,
|
|
74
|
-
ref: setContainerEl,
|
|
75
|
-
children: [
|
|
76
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
77
|
-
icon: FlipHorizontal,
|
|
78
|
-
title: t("image.flipHorizontal"),
|
|
79
|
-
onClick: onFlipX
|
|
80
|
-
}),
|
|
81
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
82
|
-
icon: FlipVertical,
|
|
83
|
-
title: t("image.flipVertical"),
|
|
84
|
-
onClick: onFlipY
|
|
85
|
-
}),
|
|
86
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
87
|
-
icon: RotateCcw,
|
|
88
|
-
title: t("image.rotateLeft"),
|
|
89
|
-
onClick: onRotateLeft
|
|
90
|
-
}),
|
|
91
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
92
|
-
icon: RotateCw,
|
|
93
|
-
title: t("image.rotateRight"),
|
|
94
|
-
onClick: onRotateRight
|
|
95
|
-
}),
|
|
96
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
97
|
-
disabled: scale === minScale,
|
|
98
|
-
icon: ZoomOut,
|
|
99
|
-
title: t("image.zoomOut"),
|
|
100
|
-
onClick: onZoomOut
|
|
101
|
-
}),
|
|
102
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
103
|
-
disabled: scale === maxScale,
|
|
104
|
-
icon: ZoomIn,
|
|
105
|
-
title: t("image.zoomIn"),
|
|
106
|
-
onClick: onZoomIn
|
|
107
|
-
}),
|
|
108
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
109
|
-
icon: Copy,
|
|
110
|
-
loading: copyLoading,
|
|
111
|
-
title: t("image.copy"),
|
|
112
|
-
onClick: handleCopy
|
|
113
|
-
}),
|
|
114
|
-
/* @__PURE__ */ jsx(ActionIcon, {
|
|
115
|
-
icon: Download,
|
|
116
|
-
loading: downloadLoading,
|
|
117
|
-
title: t("image.download"),
|
|
118
|
-
onClick: handleDownload
|
|
119
|
-
}),
|
|
120
|
-
children
|
|
121
|
-
]
|
|
122
|
-
})
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
//#endregion
|
|
126
|
-
export { Toolbar as default };
|
|
127
|
-
|
|
128
|
-
//# sourceMappingURL=Toolbar.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.mjs","names":["imageMessages","Flexbox"],"sources":["../../../src/Image/components/Toolbar.tsx"],"sourcesContent":["import { message } from 'antd';\nimport {\n Copy,\n Download,\n FlipHorizontal,\n FlipVertical,\n RotateCcw,\n RotateCw,\n ZoomIn,\n ZoomOut,\n} from 'lucide-react';\nimport { type ToolbarRenderInfoType } from 'rc-image/lib/Preview';\nimport { memo, type ReactNode, useCallback, useState } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport { Flexbox } from '@/Flex';\nimport imageMessages from '@/i18n/resources/en/image';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport { TooltipGroup } from '@/Tooltip';\nimport { getClipboardBlob } from '@/utils/blobToPng';\nimport { downloadBlob } from '@/utils/downloadBlob';\n\nimport { styles } from '../style';\n\nconst getFileNameFromUrl = (url: string): string => {\n try {\n const pathname = new URL(url).pathname;\n const match = pathname.match(/\\/([^/]+)$/);\n return match ? decodeURIComponent(match[1]) : 'image';\n } catch {\n return 'image';\n }\n};\n\nconst getExtensionFromMimeType = (mimeType: string): string => {\n const map: Record<string, string> = {\n 'image/svg+xml': 'svg',\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/jpg': 'jpg',\n 'image/webp': 'webp',\n 'image/gif': 'gif',\n };\n return map[mimeType?.toLowerCase()] || mimeType?.split('/')[1]?.split('+')[0] || 'png';\n};\n\nexport interface ToolbarProps {\n children?: ReactNode;\n info: Omit<ToolbarRenderInfoType, 'current' | 'total'>;\n maxScale: number;\n minScale: number;\n}\n\nconst Toolbar = memo<ToolbarProps>(({ children, info, minScale, maxScale }) => {\n const { t } = useTranslation(imageMessages);\n const [containerEl, setContainerEl] = useState<HTMLElement | null>(null);\n const [copyLoading, setCopyLoading] = useState(false);\n const [downloadLoading, setDownloadLoading] = useState(false);\n const {\n transform: { scale },\n actions: { onFlipY, onFlipX, onRotateLeft, onRotateRight, onZoomOut, onZoomIn },\n image: { url },\n } = info;\n\n const handleDownload = useCallback(async () => {\n setDownloadLoading(true);\n try {\n const response = await fetch(url, { mode: 'cors' });\n const blob = await response.blob();\n const blobUrl = URL.createObjectURL(blob);\n let fileName = getFileNameFromUrl(url);\n const ext = getExtensionFromMimeType(blob.type);\n if (!fileName.includes('.')) {\n fileName = `${fileName}.${ext}`;\n } else if (fileName.endsWith('.svg+xml')) {\n fileName = fileName.replace(/\\.svg\\+xml$/i, '.svg');\n }\n await downloadBlob(blobUrl, fileName);\n URL.revokeObjectURL(blobUrl);\n message.success(t('image.downloadSuccess'));\n } catch {\n message.error(t('image.downloadFailed'));\n } finally {\n setDownloadLoading(false);\n }\n }, [url, t]);\n\n const handleCopy = useCallback(async () => {\n setCopyLoading(true);\n try {\n const response = await fetch(url, { mode: 'cors' });\n const blob = await response.blob();\n const clipboardBlob = await getClipboardBlob(blob);\n await navigator.clipboard.write([new ClipboardItem(clipboardBlob)]);\n message.success(t('image.copySuccess'));\n } catch {\n message.error(t('image.copyFailed'));\n } finally {\n setCopyLoading(false);\n }\n }, [url, t]);\n\n return (\n <TooltipGroup popupContainer={containerEl ?? undefined}>\n <Flexbox horizontal className={styles.toolbar} gap={4} ref={setContainerEl}>\n <ActionIcon icon={FlipHorizontal} title={t('image.flipHorizontal')} onClick={onFlipX} />\n <ActionIcon icon={FlipVertical} title={t('image.flipVertical')} onClick={onFlipY} />\n <ActionIcon icon={RotateCcw} title={t('image.rotateLeft')} onClick={onRotateLeft} />\n <ActionIcon icon={RotateCw} title={t('image.rotateRight')} onClick={onRotateRight} />\n <ActionIcon\n disabled={scale === minScale}\n icon={ZoomOut}\n title={t('image.zoomOut')}\n onClick={onZoomOut}\n />\n <ActionIcon\n disabled={scale === maxScale}\n icon={ZoomIn}\n title={t('image.zoomIn')}\n onClick={onZoomIn}\n />\n <ActionIcon\n icon={Copy}\n loading={copyLoading}\n title={t('image.copy')}\n onClick={handleCopy}\n />\n <ActionIcon\n icon={Download}\n loading={downloadLoading}\n title={t('image.download')}\n onClick={handleDownload}\n />\n {children}\n </Flexbox>\n </TooltipGroup>\n );\n});\n\nexport default Toolbar;\n"],"mappings":"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"}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import Icon from "../../Icon/Icon.mjs";
|
|
2
|
-
import { styles } from "../style.mjs";
|
|
3
|
-
import Preview from "./Preview.mjs";
|
|
4
|
-
import Toolbar from "./Toolbar.mjs";
|
|
5
|
-
import { useMemo, useState } from "react";
|
|
6
|
-
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
import { cx } from "antd-style";
|
|
8
|
-
import { X } from "lucide-react";
|
|
9
|
-
//#region src/Image/components/usePreview.tsx
|
|
10
|
-
const usePreview = (props) => {
|
|
11
|
-
const [visible, setVisible] = useState(false);
|
|
12
|
-
return useMemo(() => {
|
|
13
|
-
if (props === false) return props;
|
|
14
|
-
const { onVisibleChange, onOpenChange, minScale = .32, maxScale = 32, toolbarAddon, rootClassName, imageRender, toolbarRender, actionsRender, ...rest } = props === true ? {} : props || {};
|
|
15
|
-
return {
|
|
16
|
-
actionsRender: actionsRender || ((_, info) => {
|
|
17
|
-
const originalNode = /* @__PURE__ */ jsx(Toolbar, {
|
|
18
|
-
info,
|
|
19
|
-
maxScale,
|
|
20
|
-
minScale,
|
|
21
|
-
children: toolbarAddon
|
|
22
|
-
});
|
|
23
|
-
if (toolbarRender) return toolbarRender(originalNode, info);
|
|
24
|
-
return originalNode;
|
|
25
|
-
}),
|
|
26
|
-
closeIcon: /* @__PURE__ */ jsx(Icon, {
|
|
27
|
-
color: "#fff",
|
|
28
|
-
icon: X
|
|
29
|
-
}),
|
|
30
|
-
imageRender: (originalNode, info) => {
|
|
31
|
-
const node = /* @__PURE__ */ jsx(Preview, {
|
|
32
|
-
visible,
|
|
33
|
-
children: originalNode
|
|
34
|
-
});
|
|
35
|
-
if (imageRender) return imageRender(node, info);
|
|
36
|
-
return node;
|
|
37
|
-
},
|
|
38
|
-
maxScale,
|
|
39
|
-
minScale,
|
|
40
|
-
onOpenChange: (open) => {
|
|
41
|
-
setVisible(open);
|
|
42
|
-
onOpenChange?.(open);
|
|
43
|
-
onVisibleChange?.(open, !open);
|
|
44
|
-
},
|
|
45
|
-
rootClassName: cx(styles.preview, rootClassName),
|
|
46
|
-
styles: { mask: { backdropFilter: "blur(8px)" } },
|
|
47
|
-
...rest
|
|
48
|
-
};
|
|
49
|
-
}, [
|
|
50
|
-
props,
|
|
51
|
-
visible,
|
|
52
|
-
styles
|
|
53
|
-
]);
|
|
54
|
-
};
|
|
55
|
-
//#endregion
|
|
56
|
-
export { usePreview as default, usePreview };
|
|
57
|
-
|
|
58
|
-
//# sourceMappingURL=usePreview.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePreview.mjs","names":[],"sources":["../../../src/Image/components/usePreview.tsx"],"sourcesContent":["import type { ImageProps as AntdImageProps } from 'antd';\nimport { cx } from 'antd-style';\nimport { X } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\nimport Icon from '@/Icon';\n\nimport { styles } from '../style';\nimport type { ImagePreviewOptions } from '../type';\nimport Preview from './Preview';\nimport Toolbar from './Toolbar';\n\nexport const usePreview = (\n props: ImagePreviewOptions | boolean | undefined,\n): AntdImageProps['preview'] => {\n const [visible, setVisible] = useState(false);\n\n return useMemo(() => {\n if (props === false) return props;\n\n const {\n onVisibleChange,\n onOpenChange,\n minScale = 0.32,\n maxScale = 32,\n toolbarAddon,\n rootClassName,\n imageRender,\n toolbarRender,\n actionsRender,\n ...rest\n }: ImagePreviewOptions = (props === true ? {} : props || {}) as ImagePreviewOptions;\n\n return {\n actionsRender:\n actionsRender ||\n ((_, info) => {\n const originalNode = (\n <Toolbar info={info} maxScale={maxScale} minScale={minScale}>\n {toolbarAddon}\n </Toolbar>\n );\n // 向后兼容 toolbarRender\n if (toolbarRender) return toolbarRender(originalNode, info);\n return originalNode;\n }),\n closeIcon: <Icon color={'#fff'} icon={X} />,\n imageRender: (originalNode, info) => {\n const node = <Preview visible={visible}>{originalNode}</Preview>;\n if (imageRender) return imageRender(node, info);\n return node;\n },\n maxScale,\n minScale,\n onOpenChange: (open: boolean) => {\n setVisible(open);\n // 支持新的 onOpenChange\n onOpenChange?.(open);\n // 向后兼容旧的 onVisibleChange\n onVisibleChange?.(open, !open);\n },\n rootClassName: cx(styles.preview, rootClassName),\n styles: { mask: { backdropFilter: 'blur(8px)' } },\n ...rest,\n };\n }, [props, visible, styles]);\n};\n\nexport default usePreview;\n"],"mappings":";;;;;;;;;AAYA,MAAa,cACX,UAC8B;CAC9B,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAE5C,OAAO,cAAc;EACnB,IAAI,UAAU,OAAO,OAAO;EAE5B,MAAM,EACJ,iBACA,cACA,WAAW,KACX,WAAW,IACX,cACA,eACA,aACA,eACA,eACA,GAAG,SACqB,UAAU,OAAO,CAAC,IAAI,SAAS,CAAC;EAE1D,OAAO;GACL,eACE,mBACE,GAAG,SAAS;IACZ,MAAM,eACJ,oBAAC,SAAD;KAAe;KAAgB;KAAoB;KAChD,UAAA;IACM,CAAA;IAGX,IAAI,eAAe,OAAO,cAAc,cAAc,IAAI;IAC1D,OAAO;GACT;GACF,WAAW,oBAAC,MAAD;IAAM,OAAO;IAAQ,MAAM;GAAI,CAAA;GAC1C,cAAc,cAAc,SAAS;IACnC,MAAM,OAAO,oBAAC,SAAD;KAAkB;KAAU,UAAA;IAAsB,CAAA;IAC/D,IAAI,aAAa,OAAO,YAAY,MAAM,IAAI;IAC9C,OAAO;GACT;GACA;GACA;GACA,eAAe,SAAkB;IAC/B,WAAW,IAAI;IAEf,eAAe,IAAI;IAEnB,kBAAkB,MAAM,CAAC,IAAI;GAC/B;GACA,eAAe,GAAG,OAAO,SAAS,aAAa;GAC/C,QAAQ,EAAE,MAAM,EAAE,gBAAgB,YAAY,EAAE;GAChD,GAAG;EACL;CACF,GAAG;EAAC;EAAO;EAAS;CAAM,CAAC;AAC7B"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import Icon from "../../Icon/Icon.mjs";
|
|
2
|
-
import { styles } from "../style.mjs";
|
|
3
|
-
import Preview from "./Preview.mjs";
|
|
4
|
-
import Toolbar from "./Toolbar.mjs";
|
|
5
|
-
import { useMemo, useState } from "react";
|
|
6
|
-
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
import { cx } from "antd-style";
|
|
8
|
-
import { X } from "lucide-react";
|
|
9
|
-
//#region src/Image/components/usePreviewGroup.tsx
|
|
10
|
-
const usePreview = (props) => {
|
|
11
|
-
const [visible, setVisible] = useState(false);
|
|
12
|
-
return useMemo(() => {
|
|
13
|
-
if (props === false) return props;
|
|
14
|
-
const { onVisibleChange, onOpenChange, minScale = .32, maxScale = 32, toolbarAddon, rootClassName, imageRender, toolbarRender, ...rest } = props === true ? {} : props || {};
|
|
15
|
-
return {
|
|
16
|
-
actionsRender: (_, info) => {
|
|
17
|
-
const originalNode = /* @__PURE__ */ jsx(Toolbar, {
|
|
18
|
-
info,
|
|
19
|
-
maxScale,
|
|
20
|
-
minScale,
|
|
21
|
-
children: toolbarAddon
|
|
22
|
-
});
|
|
23
|
-
if (toolbarRender) return toolbarRender(originalNode, info);
|
|
24
|
-
return originalNode;
|
|
25
|
-
},
|
|
26
|
-
closeIcon: /* @__PURE__ */ jsx(Icon, {
|
|
27
|
-
color: "#fff",
|
|
28
|
-
icon: X
|
|
29
|
-
}),
|
|
30
|
-
imageRender: (originalNode, info) => {
|
|
31
|
-
const node = /* @__PURE__ */ jsx(Preview, {
|
|
32
|
-
visible,
|
|
33
|
-
children: originalNode
|
|
34
|
-
});
|
|
35
|
-
if (imageRender) return imageRender(node, info);
|
|
36
|
-
return node;
|
|
37
|
-
},
|
|
38
|
-
maxScale,
|
|
39
|
-
minScale,
|
|
40
|
-
onOpenChange: (open, info) => {
|
|
41
|
-
setVisible(open);
|
|
42
|
-
onOpenChange?.(open, info);
|
|
43
|
-
onVisibleChange?.(open, !open, info.current);
|
|
44
|
-
},
|
|
45
|
-
rootClassName: cx(styles.preview, rootClassName),
|
|
46
|
-
...rest
|
|
47
|
-
};
|
|
48
|
-
}, [
|
|
49
|
-
props,
|
|
50
|
-
visible,
|
|
51
|
-
styles
|
|
52
|
-
]);
|
|
53
|
-
};
|
|
54
|
-
//#endregion
|
|
55
|
-
export { usePreview as default, usePreview };
|
|
56
|
-
|
|
57
|
-
//# sourceMappingURL=usePreviewGroup.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePreviewGroup.mjs","names":["componentStyles"],"sources":["../../../src/Image/components/usePreviewGroup.tsx"],"sourcesContent":["import { type GroupPreviewConfig } from 'antd/es/image/PreviewGroup';\nimport { cx } from 'antd-style';\nimport { X } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\nimport Icon from '@/Icon';\n\nimport { styles as componentStyles, styles } from '../style';\nimport { type PreviewGroupPreviewOptions } from '../type';\nimport Preview from './Preview';\nimport Toolbar from './Toolbar';\n\nexport const usePreview = (\n props: PreviewGroupPreviewOptions | boolean | undefined,\n): GroupPreviewConfig | boolean => {\n const [visible, setVisible] = useState(false);\n\n return useMemo(() => {\n if (props === false) return props;\n\n const {\n onVisibleChange,\n onOpenChange,\n minScale = 0.32,\n maxScale = 32,\n toolbarAddon,\n rootClassName,\n imageRender,\n toolbarRender,\n ...rest\n }: PreviewGroupPreviewOptions = (\n props === true ? {} : props || {}\n ) as PreviewGroupPreviewOptions;\n\n return {\n actionsRender: (_, info) => {\n const originalNode = (\n <Toolbar info={info} maxScale={maxScale} minScale={minScale}>\n {toolbarAddon}\n </Toolbar>\n );\n if (toolbarRender) return toolbarRender(originalNode, info);\n return originalNode;\n },\n closeIcon: <Icon color={'#fff'} icon={X} />,\n\n imageRender: (originalNode, info) => {\n const node = <Preview visible={visible}>{originalNode}</Preview>;\n if (imageRender) return imageRender(node, info);\n return node;\n },\n maxScale,\n minScale,\n onOpenChange: (open: boolean, info: { current: number }) => {\n setVisible(open);\n // 支持新的 onOpenChange\n onOpenChange?.(open, info);\n // 向后兼容旧的 onVisibleChange (注意参数差异)\n onVisibleChange?.(open, !open, info.current);\n },\n rootClassName: cx(styles.preview, rootClassName),\n ...rest,\n } satisfies GroupPreviewConfig;\n }, [props, visible, componentStyles]);\n};\n\nexport default usePreview;\n"],"mappings":";;;;;;;;;AAYA,MAAa,cACX,UACiC;CACjC,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAE5C,OAAO,cAAc;EACnB,IAAI,UAAU,OAAO,OAAO;EAE5B,MAAM,EACJ,iBACA,cACA,WAAW,KACX,WAAW,IACX,cACA,eACA,aACA,eACA,GAAG,SAEH,UAAU,OAAO,CAAC,IAAI,SAAS,CAAC;EAGlC,OAAO;GACL,gBAAgB,GAAG,SAAS;IAC1B,MAAM,eACJ,oBAAC,SAAD;KAAe;KAAgB;KAAoB;KAChD,UAAA;IACM,CAAA;IAEX,IAAI,eAAe,OAAO,cAAc,cAAc,IAAI;IAC1D,OAAO;GACT;GACA,WAAW,oBAAC,MAAD;IAAM,OAAO;IAAQ,MAAM;GAAI,CAAA;GAE1C,cAAc,cAAc,SAAS;IACnC,MAAM,OAAO,oBAAC,SAAD;KAAkB;KAAU,UAAA;IAAsB,CAAA;IAC/D,IAAI,aAAa,OAAO,YAAY,MAAM,IAAI;IAC9C,OAAO;GACT;GACA;GACA;GACA,eAAe,MAAe,SAA8B;IAC1D,WAAW,IAAI;IAEf,eAAe,MAAM,IAAI;IAEzB,kBAAkB,MAAM,CAAC,MAAM,KAAK,OAAO;GAC7C;GACA,eAAe,GAAG,OAAO,SAAS,aAAa;GAC/C,GAAG;EACL;CACF,GAAG;EAAC;EAAO;EAASA;CAAe,CAAC;AACtC"}
|