@lobehub/ui 5.25.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.
Files changed (62) hide show
  1. package/es/Image/Image.mjs +138 -37
  2. package/es/Image/Image.mjs.map +1 -1
  3. package/es/Image/PreviewGroup.d.mts +1 -0
  4. package/es/Image/PreviewGroup.mjs +33 -10
  5. package/es/Image/PreviewGroup.mjs.map +1 -1
  6. package/es/Image/index.d.mts +2 -2
  7. package/es/Image/index.mjs +1 -1
  8. package/es/Image/style.mjs +126 -71
  9. package/es/Image/style.mjs.map +1 -1
  10. package/es/Image/type.d.mts +14 -17
  11. package/es/Image/viewer/GalleryNav.mjs +44 -0
  12. package/es/Image/viewer/GalleryNav.mjs.map +1 -0
  13. package/es/Image/viewer/ImageViewer.mjs +275 -0
  14. package/es/Image/viewer/ImageViewer.mjs.map +1 -0
  15. package/es/Image/viewer/PreviewOutlet.mjs +19 -0
  16. package/es/Image/viewer/PreviewOutlet.mjs.map +1 -0
  17. package/es/Image/viewer/Toolbar.mjs +184 -0
  18. package/es/Image/viewer/Toolbar.mjs.map +1 -0
  19. package/es/Image/viewer/ViewerChrome.mjs +54 -0
  20. package/es/Image/viewer/ViewerChrome.mjs.map +1 -0
  21. package/es/Image/viewer/geometry.mjs +85 -0
  22. package/es/Image/viewer/geometry.mjs.map +1 -0
  23. package/es/Image/viewer/registry.d.mts +2 -0
  24. package/es/Image/viewer/registry.mjs +52 -0
  25. package/es/Image/viewer/registry.mjs.map +1 -0
  26. package/es/Image/viewer/useChromeIdle.mjs +72 -0
  27. package/es/Image/viewer/useChromeIdle.mjs.map +1 -0
  28. package/es/Image/viewer/useFinalFocus.mjs +10 -0
  29. package/es/Image/viewer/useFinalFocus.mjs.map +1 -0
  30. package/es/Image/viewer/useFlipTransition.mjs +321 -0
  31. package/es/Image/viewer/useFlipTransition.mjs.map +1 -0
  32. package/es/Image/viewer/useGalleryNav.mjs +89 -0
  33. package/es/Image/viewer/useGalleryNav.mjs.map +1 -0
  34. package/es/Image/viewer/useRefitTransition.mjs +47 -0
  35. package/es/Image/viewer/useRefitTransition.mjs.map +1 -0
  36. package/es/Image/viewer/useViewerGestures.mjs +148 -0
  37. package/es/Image/viewer/useViewerGestures.mjs.map +1 -0
  38. package/es/Image/viewer/useZoomPan.mjs +346 -0
  39. package/es/Image/viewer/useZoomPan.mjs.map +1 -0
  40. package/es/base-ui/Toast/hostGuard.mjs +26 -0
  41. package/es/base-ui/Toast/hostGuard.mjs.map +1 -0
  42. package/es/base-ui/Toast/imperative.mjs +43 -20
  43. package/es/base-ui/Toast/imperative.mjs.map +1 -1
  44. package/es/base-ui/Toast/pendingQueue.mjs +30 -0
  45. package/es/base-ui/Toast/pendingQueue.mjs.map +1 -0
  46. package/es/base-ui/index.mjs +1 -1
  47. package/es/i18n/resources/en/image.d.mts +5 -0
  48. package/es/i18n/resources/en/image.mjs +6 -1
  49. package/es/i18n/resources/en/image.mjs.map +1 -1
  50. package/es/i18n/resources/zhCn/image.d.mts +5 -0
  51. package/es/i18n/resources/zhCn/image.mjs +6 -1
  52. package/es/i18n/resources/zhCn/image.mjs.map +1 -1
  53. package/es/index.mjs +8 -8
  54. package/package.json +1 -1
  55. package/es/Image/components/Preview.mjs +0 -23
  56. package/es/Image/components/Preview.mjs.map +0 -1
  57. package/es/Image/components/Toolbar.mjs +0 -129
  58. package/es/Image/components/Toolbar.mjs.map +0 -1
  59. package/es/Image/components/usePreview.mjs +0 -58
  60. package/es/Image/components/usePreview.mjs.map +0 -1
  61. package/es/Image/components/usePreviewGroup.mjs +0 -57
  62. package/es/Image/components/usePreviewGroup.mjs.map +0 -1
@@ -1,5 +1,6 @@
1
1
  //#region src/i18n/resources/en/image.d.ts
2
2
  declare const _default: {
3
+ readonly 'image.close': "Close";
3
4
  readonly 'image.copy': "Copy";
4
5
  readonly 'image.copyFailed': "Copy Failed";
5
6
  readonly 'image.copySuccess': "Copy Success";
@@ -8,10 +9,14 @@ declare const _default: {
8
9
  readonly 'image.downloadSuccess': "Download Success";
9
10
  readonly 'image.flipHorizontal': "Flip Horizontal";
10
11
  readonly 'image.flipVertical': "Flip Vertical";
12
+ readonly 'image.more': "More";
13
+ readonly 'image.next': "Next";
14
+ readonly 'image.prev': "Previous";
11
15
  readonly 'image.rotateLeft': "Rotate Left";
12
16
  readonly 'image.rotateRight': "Rotate Right";
13
17
  readonly 'image.zoomIn': "Zoom In";
14
18
  readonly 'image.zoomOut': "Zoom Out";
19
+ readonly 'image.zoomReset': "Reset Zoom";
15
20
  };
16
21
  //#endregion
17
22
  export { _default as default };
@@ -1,5 +1,6 @@
1
1
  //#region src/i18n/resources/en/image.ts
2
2
  var image_default = {
3
+ "image.close": "Close",
3
4
  "image.copy": "Copy",
4
5
  "image.copyFailed": "Copy Failed",
5
6
  "image.copySuccess": "Copy Success",
@@ -8,10 +9,14 @@ var image_default = {
8
9
  "image.downloadSuccess": "Download Success",
9
10
  "image.flipHorizontal": "Flip Horizontal",
10
11
  "image.flipVertical": "Flip Vertical",
12
+ "image.more": "More",
13
+ "image.next": "Next",
14
+ "image.prev": "Previous",
11
15
  "image.rotateLeft": "Rotate Left",
12
16
  "image.rotateRight": "Rotate Right",
13
17
  "image.zoomIn": "Zoom In",
14
- "image.zoomOut": "Zoom Out"
18
+ "image.zoomOut": "Zoom Out",
19
+ "image.zoomReset": "Reset Zoom"
15
20
  };
16
21
  //#endregion
17
22
  export { image_default as default };
@@ -1 +1 @@
1
- {"version":3,"file":"image.mjs","names":[],"sources":["../../../../src/i18n/resources/en/image.ts"],"sourcesContent":["export default {\n 'image.copy': 'Copy',\n 'image.copyFailed': 'Copy Failed',\n 'image.copySuccess': 'Copy Success',\n 'image.download': 'Download',\n 'image.downloadFailed': 'Download Failed',\n 'image.downloadSuccess': 'Download Success',\n 'image.flipHorizontal': 'Flip Horizontal',\n 'image.flipVertical': 'Flip Vertical',\n 'image.rotateLeft': 'Rotate Left',\n 'image.rotateRight': 'Rotate Right',\n 'image.zoomIn': 'Zoom In',\n 'image.zoomOut': 'Zoom Out',\n} as const;\n"],"mappings":";AAAA,IAAA,gBAAe;CACb,cAAc;CACd,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,wBAAwB;CACxB,yBAAyB;CACzB,wBAAwB;CACxB,sBAAsB;CACtB,oBAAoB;CACpB,qBAAqB;CACrB,gBAAgB;CAChB,iBAAiB;AACnB"}
1
+ {"version":3,"file":"image.mjs","names":[],"sources":["../../../../src/i18n/resources/en/image.ts"],"sourcesContent":["export default {\n 'image.close': 'Close',\n 'image.copy': 'Copy',\n 'image.copyFailed': 'Copy Failed',\n 'image.copySuccess': 'Copy Success',\n 'image.download': 'Download',\n 'image.downloadFailed': 'Download Failed',\n 'image.downloadSuccess': 'Download Success',\n 'image.flipHorizontal': 'Flip Horizontal',\n 'image.flipVertical': 'Flip Vertical',\n 'image.more': 'More',\n 'image.next': 'Next',\n 'image.prev': 'Previous',\n 'image.rotateLeft': 'Rotate Left',\n 'image.rotateRight': 'Rotate Right',\n 'image.zoomIn': 'Zoom In',\n 'image.zoomOut': 'Zoom Out',\n 'image.zoomReset': 'Reset Zoom',\n} as const;\n"],"mappings":";AAAA,IAAA,gBAAe;CACb,eAAe;CACf,cAAc;CACd,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,wBAAwB;CACxB,yBAAyB;CACzB,wBAAwB;CACxB,sBAAsB;CACtB,cAAc;CACd,cAAc;CACd,cAAc;CACd,oBAAoB;CACpB,qBAAqB;CACrB,gBAAgB;CAChB,iBAAiB;CACjB,mBAAmB;AACrB"}
@@ -1,5 +1,6 @@
1
1
  //#region src/i18n/resources/zhCn/image.d.ts
2
2
  declare const _default: {
3
+ readonly 'image.close': "关闭";
3
4
  readonly 'image.copy': "复制";
4
5
  readonly 'image.copyFailed': "复制失败";
5
6
  readonly 'image.copySuccess': "复制成功";
@@ -8,10 +9,14 @@ declare const _default: {
8
9
  readonly 'image.downloadSuccess': "下载成功";
9
10
  readonly 'image.flipHorizontal': "水平翻转";
10
11
  readonly 'image.flipVertical': "垂直翻转";
12
+ readonly 'image.more': "更多";
13
+ readonly 'image.next': "下一张";
14
+ readonly 'image.prev': "上一张";
11
15
  readonly 'image.rotateLeft': "向左旋转";
12
16
  readonly 'image.rotateRight': "向右旋转";
13
17
  readonly 'image.zoomIn': "放大";
14
18
  readonly 'image.zoomOut': "缩小";
19
+ readonly 'image.zoomReset': "重置缩放";
15
20
  };
16
21
  //#endregion
17
22
  export { _default as default };
@@ -1,5 +1,6 @@
1
1
  //#region src/i18n/resources/zhCn/image.ts
2
2
  var image_default = {
3
+ "image.close": "关闭",
3
4
  "image.copy": "复制",
4
5
  "image.copyFailed": "复制失败",
5
6
  "image.copySuccess": "复制成功",
@@ -8,10 +9,14 @@ var image_default = {
8
9
  "image.downloadSuccess": "下载成功",
9
10
  "image.flipHorizontal": "水平翻转",
10
11
  "image.flipVertical": "垂直翻转",
12
+ "image.more": "更多",
13
+ "image.next": "下一张",
14
+ "image.prev": "上一张",
11
15
  "image.rotateLeft": "向左旋转",
12
16
  "image.rotateRight": "向右旋转",
13
17
  "image.zoomIn": "放大",
14
- "image.zoomOut": "缩小"
18
+ "image.zoomOut": "缩小",
19
+ "image.zoomReset": "重置缩放"
15
20
  };
16
21
  //#endregion
17
22
  export { image_default as default };
@@ -1 +1 @@
1
- {"version":3,"file":"image.mjs","names":[],"sources":["../../../../src/i18n/resources/zhCn/image.ts"],"sourcesContent":["export default {\n 'image.copy': '复制',\n 'image.copyFailed': '复制失败',\n 'image.copySuccess': '复制成功',\n 'image.download': '下载',\n 'image.downloadFailed': '下载失败',\n 'image.downloadSuccess': '下载成功',\n 'image.flipHorizontal': '水平翻转',\n 'image.flipVertical': '垂直翻转',\n 'image.rotateLeft': '向左旋转',\n 'image.rotateRight': '向右旋转',\n 'image.zoomIn': '放大',\n 'image.zoomOut': '缩小',\n} as const;\n"],"mappings":";AAAA,IAAA,gBAAe;CACb,cAAc;CACd,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,wBAAwB;CACxB,yBAAyB;CACzB,wBAAwB;CACxB,sBAAsB;CACtB,oBAAoB;CACpB,qBAAqB;CACrB,gBAAgB;CAChB,iBAAiB;AACnB"}
1
+ {"version":3,"file":"image.mjs","names":[],"sources":["../../../../src/i18n/resources/zhCn/image.ts"],"sourcesContent":["export default {\n 'image.close': '关闭',\n 'image.copy': '复制',\n 'image.copyFailed': '复制失败',\n 'image.copySuccess': '复制成功',\n 'image.download': '下载',\n 'image.downloadFailed': '下载失败',\n 'image.downloadSuccess': '下载成功',\n 'image.flipHorizontal': '水平翻转',\n 'image.flipVertical': '垂直翻转',\n 'image.more': '更多',\n 'image.next': '下一张',\n 'image.prev': '上一张',\n 'image.rotateLeft': '向左旋转',\n 'image.rotateRight': '向右旋转',\n 'image.zoomIn': '放大',\n 'image.zoomOut': '缩小',\n 'image.zoomReset': '重置缩放',\n} as const;\n"],"mappings":";AAAA,IAAA,gBAAe;CACb,eAAe;CACf,cAAc;CACd,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,wBAAwB;CACxB,yBAAyB;CACzB,wBAAwB;CACxB,sBAAsB;CACtB,cAAc;CACd,cAAc;CACd,cAAc;CACd,oBAAoB;CACpB,qBAAqB;CACrB,gBAAgB;CAChB,iBAAiB;CACjB,mBAAmB;AACrB"}
package/es/index.mjs CHANGED
@@ -112,7 +112,15 @@ import Segmented from "./Segmented/Segmented.mjs";
112
112
  import { AUTO_HEIGHT_MESSAGE_TYPE } from "./HtmlPreview/injectAutoHeightScript.mjs";
113
113
  import { HtmlPreviewIframe } from "./HtmlPreview/Iframe.mjs";
114
114
  import HtmlPreview from "./HtmlPreview/HtmlPreview.mjs";
115
+ import SkeletonBlock from "./Skeleton/SkeletonBlock.mjs";
116
+ import SkeletonAvatar from "./Skeleton/SkeletonAvatar.mjs";
117
+ import SkeletonParagraph from "./Skeleton/SkeletonParagraph.mjs";
118
+ import SkeletonTitle from "./Skeleton/SkeletonTitle.mjs";
119
+ import SkeletonButton from "./Skeleton/SkeletonButton.mjs";
120
+ import SkeletonTags from "./Skeleton/SkeletonTags.mjs";
121
+ import Skeleton from "./Skeleton/index.mjs";
115
122
  import PreviewGroup from "./Image/PreviewGroup.mjs";
123
+ import { ToastHost, toast, useToast } from "./base-ui/Toast/imperative.mjs";
116
124
  import Image from "./Image/index.mjs";
117
125
  import ImageSelect from "./ImageSelect/ImageSelect.mjs";
118
126
  import { LayoutFooter } from "./Layout/components/LayoutFooter.mjs";
@@ -147,17 +155,9 @@ import { ScrollArea } from "./base-ui/ScrollArea/ScrollArea.mjs";
147
155
  import SearchBar from "./SearchBar/SearchBar.mjs";
148
156
  import Select from "./Select/Select.mjs";
149
157
  import SideNav from "./SideNav/SideNav.mjs";
150
- import SkeletonBlock from "./Skeleton/SkeletonBlock.mjs";
151
- import SkeletonAvatar from "./Skeleton/SkeletonAvatar.mjs";
152
- import SkeletonParagraph from "./Skeleton/SkeletonParagraph.mjs";
153
- import SkeletonTitle from "./Skeleton/SkeletonTitle.mjs";
154
- import SkeletonButton from "./Skeleton/SkeletonButton.mjs";
155
- import SkeletonTags from "./Skeleton/SkeletonTags.mjs";
156
- import Skeleton from "./Skeleton/index.mjs";
157
158
  import SliderWithInput from "./SliderWithInput/SliderWithInput.mjs";
158
159
  import SortableList from "./SortableList/SortableList.mjs";
159
160
  import ThemeSwitch from "./ThemeSwitch/ThemeSwitch.mjs";
160
- import { ToastHost, toast, useToast } from "./base-ui/Toast/imperative.mjs";
161
161
  import Toc from "./Toc/Toc.mjs";
162
162
  import { ErrorBoundary } from "react-error-boundary";
163
163
  export { A, Accordion, AccordionItem, ActionIcon, ActionIconGroup, Alert, AutoComplete, Avatar, AvatarGroup, Block, Burger, Button, CLASSNAMES, Center, Checkbox, CheckboxGroup, CodeDiff, CodeEditor, Collapse, ColorSwatches, ConfigProvider, ContextMenuHost, ContextMenuTrigger, CopyButton, DatePicker, DownloadButton, DraggablePanel, DraggablePanelBody, DraggablePanelContainer, DraggablePanelFooter, DraggablePanelHeader, DraggableSideNav, Drawer, Dropdown, DropdownMenu, DropdownMenuCheckboxItemIndicator, DropdownMenuCheckboxItemPrimitive, DropdownMenuFooter, DropdownMenuGroup, DropdownMenuGroupLabel, DropdownMenuHeader, DropdownMenuItem, DropdownMenuItemContent, DropdownMenuItemExtra, DropdownMenuItemIcon, DropdownMenuItemLabel, DropdownMenuPopup, DropdownMenuPortal, DropdownMenuPositioner, DropdownMenuRoot, DropdownMenuScrollViewport, DropdownMenuSeparator, DropdownMenuSubmenuArrow, DropdownMenuSubmenuRoot, DropdownMenuSubmenuTrigger, DropdownMenuTrigger, EditableText, EditorSlashMenu, EmojiPicker, Empty, ErrorBoundary, FileTypeIcon, FlexBasic_default as FlexBasic, FlexBasic_default as Flexbox, FluentEmoji, FontLoader, Footer, Form, FormGroup, FormItem, FormModal, FormSubmitFooter, FormTitle, Freeze, Grid, GroupAvatar, GuideCard, DEFAULT_HEIGHT as HTML_PREVIEW_DEFAULT_HEIGHT, DEFAULT_SANDBOX as HTML_PREVIEW_DEFAULT_SANDBOX, AUTO_HEIGHT_MESSAGE_TYPE as HTML_PREVIEW_RESIZE_MESSAGE, Header, Highlighter, Hotkey, HotkeyInput, HtmlPreview, HtmlPreviewIframe, I18nProvider, Icon, IconProvider, Image, ImageSelect, Input, InputNumber, InputOPT, InputPassword, KeyMapEnum, LOBE_THEME_APP_ID, Layout, LayoutFooter, LayoutHeader, LayoutMain, LayoutSidebar, LayoutSidebarInner, LayoutToc, List, ListItem, I18nProvider as LobeUIProvider, Markdown, MaskShadow, MaterialFileTypeIcon, Menu, Mermaid, Meta, Modal, ModalHost, ModalProvider, MotionComponent, MotionProvider, NeuralNetworkLoading, PatchDiff, Popover, PopoverArrow, PopoverArrowIcon, PopoverBackdrop, PopoverGroup, PopoverPopup, PopoverPortal, PopoverPositioner, PopoverProvider, PopoverRoot, PopoverTriggerElement, PopoverViewport, PreviewGroup, ScrollArea, ScrollAreaContent, ScrollAreaCorner, ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport, ScrollShadow, SearchBar, SearchResultCards, Segmented, Select, lobe_theme_default as ShikiLobeTheme, SideNav, Skeleton, SkeletonAvatar, SkeletonBlock, SkeletonButton, SkeletonParagraph, SkeletonTags, SkeletonTitle, SliderWithInput, Snippet, SortableList, SyntaxHighlighter, SyntaxMermaid, Tabs, Tag, Text, TextArea, ThemeProvider, ThemeSwitch, ToastHost, Toc, Tooltip, TooltipGroup, Typography, Video, closeContextMenu, combineKeys, copyToClipboard, createModal, createRawModal, findCustomThemeName, genCdnUrl, generateColorNeutralPalette, generateColorPalette, highlighterThemes, containsScript as htmlPreviewContainsScript, isFullHtmlDocument, isHtmlContentClosed, generateCustomStylish as lobeCustomStylish, generateCustomToken as lobeCustomToken, staticStylish as lobeStaticStylish, styles as menuSharedStyles, mermaidThemes, neutralColors, neutralColorsSwatches, placementMap, preprocessMarkdownContent, preventDefault, preventDefaultAndStopPropagation, primaryColors, primaryColorsSwatches, rehypeCustomFootnotes, rehypeKatexDir, rehypeStreamAnimated, remarkBr, remarkColor, remarkCustomFootnotes, remarkGfmPlus, remarkVideo, renderDropdownMenuItems, setContextMenuInterceptor, showContextMenu, stopPropagation, toFloatingUIPlacement, toast, updateContextMenuItems, useAppElement, useCdnFn, useModalContext, useMotionComponent, usePopoverContext, usePopoverPortalContainer, useToast, useTranslation };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/ui",
3
- "version": "5.25.0",
3
+ "version": "5.26.0",
4
4
  "description": "Lobe UI is an open-source UI component library for building AIGC web apps",
5
5
  "keywords": [
6
6
  "lobehub",
@@ -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,129 +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 blob = await (await fetch(url, { mode: "cors" })).blob();
60
- const clipboardBlob = await getClipboardBlob(blob);
61
- await navigator.clipboard.write([new ClipboardItem(clipboardBlob)]);
62
- message.success(t("image.copySuccess"));
63
- } catch {
64
- message.error(t("image.copyFailed"));
65
- } finally {
66
- setCopyLoading(false);
67
- }
68
- }, [url, t]);
69
- return /* @__PURE__ */ jsx(TooltipGroup, {
70
- popupContainer: containerEl ?? void 0,
71
- children: /* @__PURE__ */ jsxs(FlexBasic_default, {
72
- horizontal: true,
73
- className: styles.toolbar,
74
- gap: 4,
75
- ref: setContainerEl,
76
- children: [
77
- /* @__PURE__ */ jsx(ActionIcon, {
78
- icon: FlipHorizontal,
79
- title: t("image.flipHorizontal"),
80
- onClick: onFlipX
81
- }),
82
- /* @__PURE__ */ jsx(ActionIcon, {
83
- icon: FlipVertical,
84
- title: t("image.flipVertical"),
85
- onClick: onFlipY
86
- }),
87
- /* @__PURE__ */ jsx(ActionIcon, {
88
- icon: RotateCcw,
89
- title: t("image.rotateLeft"),
90
- onClick: onRotateLeft
91
- }),
92
- /* @__PURE__ */ jsx(ActionIcon, {
93
- icon: RotateCw,
94
- title: t("image.rotateRight"),
95
- onClick: onRotateRight
96
- }),
97
- /* @__PURE__ */ jsx(ActionIcon, {
98
- disabled: scale === minScale,
99
- icon: ZoomOut,
100
- title: t("image.zoomOut"),
101
- onClick: onZoomOut
102
- }),
103
- /* @__PURE__ */ jsx(ActionIcon, {
104
- disabled: scale === maxScale,
105
- icon: ZoomIn,
106
- title: t("image.zoomIn"),
107
- onClick: onZoomIn
108
- }),
109
- /* @__PURE__ */ jsx(ActionIcon, {
110
- icon: Copy,
111
- loading: copyLoading,
112
- title: t("image.copy"),
113
- onClick: handleCopy
114
- }),
115
- /* @__PURE__ */ jsx(ActionIcon, {
116
- icon: Download,
117
- loading: downloadLoading,
118
- title: t("image.download"),
119
- onClick: handleDownload
120
- }),
121
- children
122
- ]
123
- })
124
- });
125
- });
126
- //#endregion
127
- export { Toolbar as default };
128
-
129
- //# 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"}