@lobehub/ui 5.2.2 → 5.4.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 (186) hide show
  1. package/es/Accordion/Accordion.d.mts +2 -2
  2. package/es/Accordion/AccordionItem.d.mts +2 -2
  3. package/es/ActionIcon/ActionIcon.d.mts +2 -2
  4. package/es/Alert/Alert.d.mts +2 -2
  5. package/es/AutoComplete/Select.d.mts +2 -2
  6. package/es/Avatar/AvatarGroup/index.d.mts +2 -2
  7. package/es/Burger/Burger.d.mts +2 -2
  8. package/es/CodeDiff/CodeDiff.d.mts +2 -2
  9. package/es/CodeDiff/PatchDiff.d.mts +2 -2
  10. package/es/CodeEditor/CodeEditor.d.mts +2 -2
  11. package/es/Collapse/Collapse.d.mts +2 -2
  12. package/es/ConfigProvider/index.d.mts +2 -2
  13. package/es/CopyButton/CopyButton.d.mts +2 -2
  14. package/es/DatePicker/DatePicker.d.mts +2 -2
  15. package/es/DraggablePanel/components/DraggablePanelBody.d.mts +2 -2
  16. package/es/DraggablePanel/components/DraggablePanelContainer.d.mts +2 -2
  17. package/es/DraggablePanel/components/DraggablePanelFooter.d.mts +2 -2
  18. package/es/DraggablePanel/components/DraggablePanelHeader.d.mts +2 -2
  19. package/es/DraggableSideNav/DraggableSideNav.d.mts +2 -2
  20. package/es/Drawer/Drawer.d.mts +2 -2
  21. package/es/Dropdown/Dropdown.d.mts +2 -2
  22. package/es/EditableText/EditableText.d.mts +2 -2
  23. package/es/EditorSlashMenu/atoms.d.mts +13 -13
  24. package/es/EmojiPicker/EmojiPicker.d.mts +2 -2
  25. package/es/Flex/FlexBasic.d.mts +2 -2
  26. package/es/FontLoader/index.d.mts +2 -2
  27. package/es/Footer/Footer.d.mts +2 -2
  28. package/es/Form/components/FormGroup.d.mts +2 -2
  29. package/es/Form/components/FormItem.d.mts +2 -2
  30. package/es/Form/components/FormSubmitFooter.d.mts +2 -2
  31. package/es/FormModal/FormModal.d.mts +2 -2
  32. package/es/Freeze/Freeze.d.mts +2 -2
  33. package/es/GuideCard/GuideCard.d.mts +2 -2
  34. package/es/Header/Header.d.mts +2 -2
  35. package/es/Highlighter/Highlighter.d.mts +2 -2
  36. package/es/Highlighter/SyntaxHighlighter/index.d.mts +2 -2
  37. package/es/Hotkey/Hotkey.d.mts +2 -2
  38. package/es/HotkeyInput/HotkeyInput.d.mts +2 -2
  39. package/es/HotkeyInput/HotkeyInput.mjs +30 -8
  40. package/es/HotkeyInput/HotkeyInput.mjs.map +1 -1
  41. package/es/HotkeyInput/type.d.mts +3 -0
  42. package/es/Icon/Icon.d.mts +2 -2
  43. package/es/Icon/components/IconProvider.d.mts +3 -3
  44. package/es/Image/Image.mjs +2 -2
  45. package/es/Image/Image.mjs.map +1 -1
  46. package/es/Image/PreviewGroup.d.mts +2 -2
  47. package/es/Image/components/Toolbar.mjs +116 -36
  48. package/es/Image/components/Toolbar.mjs.map +1 -1
  49. package/es/Input/Input.d.mts +2 -2
  50. package/es/Input/InputOPT.d.mts +2 -2
  51. package/es/Input/InputPassword.d.mts +2 -2
  52. package/es/Input/TextArea.d.mts +2 -2
  53. package/es/Layout/components/LayoutFooter.d.mts +2 -2
  54. package/es/Layout/components/LayoutHeader.d.mts +2 -2
  55. package/es/Layout/components/LayoutMain.d.mts +2 -2
  56. package/es/Layout/components/LayoutSidebar.d.mts +2 -2
  57. package/es/Layout/components/LayoutSidebarInner.d.mts +2 -2
  58. package/es/Layout/components/LayoutToc.d.mts +2 -2
  59. package/es/List/ListItem/index.d.mts +2 -2
  60. package/es/Markdown/Markdown.d.mts +2 -2
  61. package/es/Markdown/Markdown.mjs +2 -1
  62. package/es/Markdown/Markdown.mjs.map +1 -1
  63. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs +56 -30
  64. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs.map +1 -1
  65. package/es/Markdown/SyntaxMarkdown/style.mjs +2 -2
  66. package/es/Markdown/SyntaxMarkdown/style.mjs.map +1 -1
  67. package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs +229 -0
  68. package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs.map +1 -0
  69. package/es/Markdown/SyntaxMarkdown/useStreamQueue.mjs +8 -6
  70. package/es/Markdown/SyntaxMarkdown/useStreamQueue.mjs.map +1 -1
  71. package/es/Markdown/Typography.d.mts +2 -2
  72. package/es/Markdown/components/SearchResultCards/index.d.mts +2 -2
  73. package/es/Markdown/index.d.mts +2 -2
  74. package/es/Markdown/plugins/rehypeStreamAnimated.d.mts +2 -0
  75. package/es/Markdown/plugins/rehypeStreamAnimated.mjs +17 -5
  76. package/es/Markdown/plugins/rehypeStreamAnimated.mjs.map +1 -1
  77. package/es/Markdown/type.d.mts +3 -1
  78. package/es/MaskShadow/MaskShadow.d.mts +2 -2
  79. package/es/Menu/Menu.d.mts +2 -2
  80. package/es/Mermaid/Mermaid.d.mts +2 -2
  81. package/es/Mermaid/SyntaxMermaid/index.d.mts +2 -2
  82. package/es/Modal/Modal.d.mts +2 -2
  83. package/es/Modal/ModalProvider.d.mts +2 -2
  84. package/es/Modal/imperative.d.mts +2 -2
  85. package/es/MotionProvider/index.d.mts +2 -2
  86. package/es/Popover/ArrowIcon.d.mts +2 -2
  87. package/es/Popover/atoms.d.mts +2 -2
  88. package/es/Popover/context.d.mts +2 -2
  89. package/es/SearchBar/SearchBar.d.mts +2 -2
  90. package/es/Segmented/Segmented.d.mts +2 -2
  91. package/es/Select/Select.d.mts +2 -2
  92. package/es/SideNav/SideNav.d.mts +2 -2
  93. package/es/SliderWithInput/SliderWithInput.d.mts +2 -2
  94. package/es/SortableList/components/DragHandle.d.mts +2 -2
  95. package/es/SortableList/components/SortableItem.d.mts +2 -2
  96. package/es/ThemeProvider/ThemeProvider.d.mts +2 -2
  97. package/es/Toc/Toc.d.mts +2 -2
  98. package/es/Tooltip/TooltipGroup.mjs +4 -3
  99. package/es/Tooltip/TooltipGroup.mjs.map +1 -1
  100. package/es/Tooltip/TooltipStandalone.mjs +18 -5
  101. package/es/Tooltip/TooltipStandalone.mjs.map +1 -1
  102. package/es/Tooltip/type.d.mts +7 -0
  103. package/es/Tooltip/useMergedTooltipProps.mjs +4 -1
  104. package/es/Tooltip/useMergedTooltipProps.mjs.map +1 -1
  105. package/es/Video/index.d.mts +2 -2
  106. package/es/awesome/AuroraBackground/AuroraBackground.d.mts +2 -2
  107. package/es/awesome/BottomGradientButton/BottomGradientButton.d.mts +2 -2
  108. package/es/awesome/Features/Features.d.mts +2 -2
  109. package/es/awesome/Giscus/Giscus.d.mts +2 -2
  110. package/es/awesome/GradientButton/GradientButton.d.mts +2 -2
  111. package/es/awesome/GridBackground/GridBackground.d.mts +2 -2
  112. package/es/awesome/GridBackground/GridShowcase.d.mts +2 -2
  113. package/es/awesome/Hero/Hero.d.mts +2 -2
  114. package/es/awesome/Spline/Spine.d.mts +2 -2
  115. package/es/awesome/Spotlight/Spotlight.d.mts +2 -2
  116. package/es/awesome/SpotlightCard/SpotlightCard.d.mts +2 -2
  117. package/es/awesome/TypewriterEffect/TypewriterEffect.d.mts +2 -2
  118. package/es/base-ui/DropdownMenu/DropdownMenu.d.mts +2 -2
  119. package/es/base-ui/DropdownMenu/atoms.d.mts +18 -18
  120. package/es/base-ui/Modal/atoms.d.mts +12 -12
  121. package/es/base-ui/Modal/context.d.mts +2 -2
  122. package/es/base-ui/Modal/imperative.d.mts +2 -2
  123. package/es/base-ui/ScrollArea/atoms.d.mts +7 -7
  124. package/es/base-ui/Select/Select.d.mts +2 -2
  125. package/es/base-ui/Select/atoms.d.mts +3 -3
  126. package/es/base-ui/Switch/Switch.d.mts +2 -2
  127. package/es/base-ui/Switch/atoms.d.mts +4 -4
  128. package/es/base-ui/Toast/imperative.d.mts +2 -2
  129. package/es/brand/LobeChat/index.d.mts +2 -2
  130. package/es/brand/LobeHub/index.d.mts +2 -2
  131. package/es/brand/LogoThree/LogoSpline.d.mts +2 -2
  132. package/es/brand/LogoThree/index.d.mts +2 -2
  133. package/es/chat/BackBottom/BackBottom.d.mts +2 -2
  134. package/es/chat/ChatInputArea/components/ChatInputAreaInner.d.mts +2 -2
  135. package/es/chat/ChatItem/ChatItem.d.mts +2 -2
  136. package/es/chat/ChatList/ChatList.d.mts +2 -2
  137. package/es/chat/EditableMessage/EditableMessage.d.mts +2 -2
  138. package/es/chat/EditableMessageList/EditableMessageList.d.mts +2 -2
  139. package/es/chat/MessageInput/MessageInput.d.mts +2 -2
  140. package/es/chat/MessageModal/MessageModal.d.mts +2 -2
  141. package/es/color/ColorScales/index.d.mts +2 -2
  142. package/es/color/CssVar/index.d.mts +2 -2
  143. package/es/i18n/context.d.mts +2 -2
  144. package/es/i18n/resources/en/hotkey.d.mts +1 -0
  145. package/es/i18n/resources/en/hotkey.mjs +1 -0
  146. package/es/i18n/resources/en/hotkey.mjs.map +1 -1
  147. package/es/i18n/resources/en/image.d.mts +18 -0
  148. package/es/i18n/resources/en/image.mjs +19 -0
  149. package/es/i18n/resources/en/image.mjs.map +1 -0
  150. package/es/i18n/resources/en/index.d.mts +4 -3
  151. package/es/i18n/resources/en/index.mjs +2 -0
  152. package/es/i18n/resources/en/index.mjs.map +1 -1
  153. package/es/i18n/resources/zhCn/hotkey.d.mts +1 -0
  154. package/es/i18n/resources/zhCn/hotkey.mjs +1 -0
  155. package/es/i18n/resources/zhCn/hotkey.mjs.map +1 -1
  156. package/es/i18n/resources/zhCn/image.d.mts +18 -0
  157. package/es/i18n/resources/zhCn/image.mjs +19 -0
  158. package/es/i18n/resources/zhCn/image.mjs.map +1 -0
  159. package/es/i18n/resources/zhCn/index.d.mts +4 -3
  160. package/es/i18n/resources/zhCn/index.mjs +2 -0
  161. package/es/i18n/resources/zhCn/index.mjs.map +1 -1
  162. package/es/i18n/types.d.mts +4 -3
  163. package/es/icons/lucideExtra/BotPromptIcon.d.mts +2 -2
  164. package/es/icons/lucideExtra/CreateBotIcon.d.mts +3 -3
  165. package/es/icons/lucideExtra/DiscordIcon.d.mts +3 -3
  166. package/es/icons/lucideExtra/GlobeOffIcon.d.mts +2 -2
  167. package/es/icons/lucideExtra/GroupBotIcon.d.mts +3 -3
  168. package/es/icons/lucideExtra/GroupBotSquareIcon.d.mts +2 -2
  169. package/es/icons/lucideExtra/LeftClickIcon.d.mts +3 -3
  170. package/es/icons/lucideExtra/LeftDoubleClickIcon.d.mts +2 -2
  171. package/es/icons/lucideExtra/McpIcon.d.mts +3 -3
  172. package/es/icons/lucideExtra/ProviderIcon.d.mts +3 -3
  173. package/es/icons/lucideExtra/RightClickIcon.d.mts +3 -3
  174. package/es/icons/lucideExtra/RightDoubleClickIcon.d.mts +3 -3
  175. package/es/icons/lucideExtra/ShapesUploadIcon.d.mts +3 -3
  176. package/es/icons/lucideExtra/SkillsIcon.d.mts +2 -2
  177. package/es/icons/lucideExtra/TreeDownRightIcon.d.mts +3 -3
  178. package/es/icons/lucideExtra/TreeUpDownRightIcon.d.mts +3 -3
  179. package/es/mdx/Mdx/index.d.mts +2 -2
  180. package/es/mobile/ChatHeader/ChatHeaderTitle.d.mts +2 -2
  181. package/es/mobile/ChatInputArea/components/ChatSendButton.d.mts +2 -2
  182. package/es/mobile/TabBar/TabBar.d.mts +2 -2
  183. package/es/storybook/StoryBook/index.d.mts +2 -2
  184. package/es/utils/blobToPng.mjs +41 -0
  185. package/es/utils/blobToPng.mjs.map +1 -0
  186. package/package.json +1 -1
@@ -12,11 +12,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
12
12
  import { cx, useThemeMode } from "antd-style";
13
13
  import useMergeState from "use-merge-value";
14
14
  import { isEqual } from "es-toolkit/compat";
15
- import { Undo2Icon } from "lucide-react";
15
+ import { Undo2Icon, XIcon } from "lucide-react";
16
16
  import { useHotkeys, useRecordHotkeys } from "react-hotkeys-hook";
17
17
 
18
18
  //#region src/HotkeyInput/HotkeyInput.tsx
19
- const HotkeyInput = memo(({ value = "", defaultValue = "", resetValue = "", onChange, onConflict, placeholder, disabled, shadow, allowReset = true, style, className, hotkeyConflicts = [], variant, texts, isApple, onBlur, onReset, onFocus }) => {
19
+ const HotkeyInput = memo(({ value = "", defaultValue = "", resetValue = "", onChange, onClear, onConflict, placeholder, disabled, shadow, allowClear, allowReset = true, style, className, hotkeyConflicts = [], variant, texts, isApple, onBlur, onReset, onFocus }) => {
20
20
  const [isFocused, setIsFocused] = useState(false);
21
21
  const [hasConflict, setHasConflict] = useState(false);
22
22
  const [hasInvalidCombination, setHasInvalidCombination] = useState(false);
@@ -106,6 +106,17 @@ const HotkeyInput = memo(({ value = "", defaultValue = "", resetValue = "", onCh
106
106
  stop();
107
107
  onBlur?.(e);
108
108
  };
109
+ const handleClear = (e) => {
110
+ e.preventDefault();
111
+ e.stopPropagation();
112
+ setHotkeyValue?.("");
113
+ resetKeys();
114
+ setHasConflict(false);
115
+ setHasInvalidCombination(false);
116
+ setIsFocused(false);
117
+ stop();
118
+ onClear?.(hotkeyValue);
119
+ };
109
120
  const handleReset = (e) => {
110
121
  e.preventDefault();
111
122
  e.stopPropagation();
@@ -125,6 +136,7 @@ const HotkeyInput = memo(({ value = "", defaultValue = "", resetValue = "", onCh
125
136
  };
126
137
  const placeholderText = placeholder ?? t("hotkey.placeholder");
127
138
  const resetTitle = texts?.reset ?? t("hotkey.reset");
139
+ const clearTitle = texts?.clear ?? t("hotkey.clear");
128
140
  const conflictText = texts?.conflicts ?? t("hotkey.conflict");
129
141
  const invalidText = texts?.invalidCombination ?? t("hotkey.invalidCombination");
130
142
  return /* @__PURE__ */ jsxs(FlexBasic_default, {
@@ -167,12 +179,22 @@ const HotkeyInput = memo(({ value = "", defaultValue = "", resetValue = "", onCh
167
179
  onBlur: handleBlur,
168
180
  onFocus: handleFocus
169
181
  }),
170
- !isFocused && allowReset && hotkeyValue && hotkeyValue !== resetValue && !disabled && /* @__PURE__ */ jsx(ActionIcon_default, {
171
- icon: Undo2Icon,
172
- size: "small",
173
- title: resetTitle,
174
- variant: "filled",
175
- onClick: handleReset
182
+ !isFocused && hotkeyValue && !disabled && (allowReset || allowClear) && /* @__PURE__ */ jsxs(FlexBasic_default, {
183
+ horizontal: true,
184
+ gap: 4,
185
+ children: [allowReset && hotkeyValue !== resetValue && /* @__PURE__ */ jsx(ActionIcon_default, {
186
+ icon: Undo2Icon,
187
+ size: "small",
188
+ title: resetTitle,
189
+ variant: "filled",
190
+ onClick: handleReset
191
+ }), allowClear && /* @__PURE__ */ jsx(ActionIcon_default, {
192
+ icon: XIcon,
193
+ size: "small",
194
+ title: clearTitle,
195
+ variant: "filled",
196
+ onClick: handleClear
197
+ })]
176
198
  })
177
199
  ]
178
200
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"HotkeyInput.mjs","names":["hotkeyMessages","useControlledState","modifiers: string[]","normalKeys: string[]","normalizedKey: any","Flexbox","Hotkey","ActionIcon"],"sources":["../../src/HotkeyInput/HotkeyInput.tsx"],"sourcesContent":["'use client';\n\nimport { type InputRef } from 'antd';\nimport { cx, useThemeMode } from 'antd-style';\nimport { isEqual } from 'es-toolkit/compat';\nimport { Undo2Icon } from 'lucide-react';\nimport {\n type FocusEvent,\n memo,\n type MouseEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useHotkeys, useRecordHotkeys } from 'react-hotkeys-hook';\nimport useControlledState from 'use-merge-value';\n\nimport ActionIcon from '@/ActionIcon';\nimport { Flexbox } from '@/Flex';\nimport Hotkey from '@/Hotkey';\nimport { checkIsAppleDevice, NORMATIVE_MODIFIER, splitKeysByPlus } from '@/Hotkey/utils';\nimport hotkeyMessages from '@/i18n/resources/en/hotkey';\nimport { useTranslation } from '@/i18n/useTranslation';\n\nimport { styles, variants } from './style';\nimport { type HotkeyInputProps } from './type';\n\nconst HotkeyInput = memo<HotkeyInputProps>(\n ({\n value = '',\n defaultValue = '',\n resetValue = '',\n onChange,\n onConflict,\n placeholder,\n disabled,\n shadow,\n allowReset = true,\n style,\n className,\n hotkeyConflicts = [],\n variant,\n texts,\n isApple,\n onBlur,\n onReset,\n onFocus,\n }) => {\n const [isFocused, setIsFocused] = useState(false);\n const [hasConflict, setHasConflict] = useState(false);\n const [hasInvalidCombination, setHasInvalidCombination] = useState(false);\n const inputRef = useRef<InputRef>(null);\n const { isDarkMode } = useThemeMode();\n const { t } = useTranslation(hotkeyMessages);\n const isAppleDevice = useMemo(() => checkIsAppleDevice(isApple), [isApple]);\n const [hotkeyValue, setHotkeyValue] = useControlledState(defaultValue, {\n defaultValue,\n onChange,\n value,\n });\n\n // 使用 useRecordHotkeys 处理快捷键录入\n const [recordedKeys, { start, stop, isRecording, resetKeys }] = useRecordHotkeys();\n\n useHotkeys(\n '*',\n () => {\n inputRef.current?.blur();\n },\n {\n enableOnContentEditable: true,\n enableOnFormTags: true,\n enabled: isRecording && !disabled,\n keydown: false,\n keyup: true,\n preventDefault: true,\n },\n );\n\n // 处理按键,保证格式正确:修饰键在前,最多一个非修饰键在后\n const formatKeys = useCallback((keysSet: Set<string>) => {\n const modifiers: string[] = [];\n const normalKeys: string[] = [];\n\n for (const key of keysSet) {\n // 处理不同表示的修饰键\n const normalizedKey: any = key.toLowerCase();\n if (NORMATIVE_MODIFIER.includes(normalizedKey)) {\n // 统一修饰键表示\n if (\n (!isAppleDevice && normalizedKey === 'ctrl') ||\n (isAppleDevice && normalizedKey === 'meta')\n ) {\n if (!modifiers.includes('mod')) modifiers.push('mod');\n } else if (!modifiers.includes(normalizedKey)) {\n modifiers.push(normalizedKey);\n }\n } else {\n normalKeys.push(key);\n }\n }\n\n // 至少需要一个修饰键\n if (modifiers.length === 0 && normalKeys.length > 0) {\n return { isValid: false, keys: [] };\n }\n\n // 只允许一个非修饰键,如果有多个,只保留最后一个\n const finalKey = normalKeys.length > 0 ? [normalKeys.at(-1)] : [];\n const shortcuts = [modifiers, finalKey];\n\n return {\n // 组合必须包含至少一个按键\n isValid: shortcuts.every((k) => k.length > 0),\n keys: shortcuts.flat(),\n };\n }, []);\n\n // 获取格式化后的按键字符串\n const { isValid, keys } = formatKeys(recordedKeys);\n const keysString = keys.join('+');\n\n // 检查快捷键冲突\n const checkHotkeyConflict = useCallback(\n (newHotkey: string): boolean => {\n return hotkeyConflicts\n .filter((conflictKey) => conflictKey !== resetValue)\n .some((conflictKey) => {\n const newKeys = splitKeysByPlus(newHotkey);\n const conflictKeys = splitKeysByPlus(conflictKey);\n return isEqual(newKeys, conflictKeys);\n });\n },\n [hotkeyConflicts],\n );\n\n // 当按键组合完成时处理结果\n useEffect(() => {\n if (recordedKeys.size > 0 && !isRecording) {\n if (!isValid) {\n setHasInvalidCombination(true);\n setHasConflict(false);\n return;\n }\n\n setHasInvalidCombination(false);\n const newKeysString = keysString;\n\n // 检查冲突\n const conflict = checkHotkeyConflict(newKeysString);\n if (conflict) {\n setHasConflict(true);\n onConflict?.(newKeysString);\n } else {\n setHasConflict(false);\n setHotkeyValue?.(newKeysString);\n }\n }\n }, [\n recordedKeys,\n isRecording,\n isValid,\n keysString,\n checkHotkeyConflict,\n setHotkeyValue,\n onConflict,\n ]);\n\n // 处理输入框焦点\n const handleFocus = (e: FocusEvent<HTMLInputElement>) => {\n if (disabled) return;\n setIsFocused(true);\n setHasConflict(false);\n setHasInvalidCombination(false);\n start(); // 开始记录\n onFocus?.(e);\n };\n\n const handleBlur = (e: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n stop(); // 停止记录\n onBlur?.(e);\n };\n\n // 重置功能\n const handleReset = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setHotkeyValue?.(resetValue);\n resetKeys();\n setHasConflict(false);\n setHasInvalidCombination(false);\n setIsFocused(false);\n stop(); // 停止记录\n onReset?.(hotkeyValue, resetValue);\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (disabled || isFocused) return;\n inputRef.current?.focus();\n };\n\n const placeholderText = placeholder ?? t('hotkey.placeholder');\n const resetTitle = texts?.reset ?? t('hotkey.reset');\n const conflictText = texts?.conflicts ?? t('hotkey.conflict');\n const invalidText = texts?.invalidCombination ?? t('hotkey.invalidCombination');\n\n return (\n <Flexbox\n className={className}\n gap={8}\n style={{\n position: 'relative',\n ...style,\n }}\n >\n <Flexbox\n horizontal\n align={'center'}\n justify={'space-between'}\n className={cx(\n variants({\n disabled,\n error: hasConflict || hasInvalidCombination,\n focused: isFocused,\n shadow,\n variant: variant || (isDarkMode ? 'filled' : 'outlined'),\n }),\n )}\n onClick={handleClick}\n >\n <div style={{ pointerEvents: 'none' }}>\n {isRecording ? (\n <span className={styles.placeholder}>\n {keys.length > 0 ? <Hotkey keys={keysString} /> : placeholderText}\n </span>\n ) : hotkeyValue ? (\n <Hotkey keys={hotkeyValue} />\n ) : (\n <span className={styles.placeholder}>{placeholderText}</span>\n )}\n </div>\n\n {/* 隐藏的输入框,用于接收焦点 */}\n <input\n readOnly\n className={styles.hiddenInput}\n disabled={disabled}\n ref={inputRef as any}\n style={{ pointerEvents: 'none' }}\n onBlur={handleBlur}\n onFocus={handleFocus}\n />\n\n {!isFocused && allowReset && hotkeyValue && hotkeyValue !== resetValue && !disabled && (\n <ActionIcon\n icon={Undo2Icon}\n size={'small'}\n title={resetTitle}\n variant={'filled'}\n onClick={handleReset}\n />\n )}\n </Flexbox>\n {hasConflict && <div className={styles.errorText}>{conflictText}</div>}\n {hasInvalidCombination && <div className={styles.errorText}>{invalidText}</div>}\n </Flexbox>\n );\n },\n);\n\nHotkeyInput.displayName = 'HotkeyInput';\n\nexport default HotkeyInput;\n"],"mappings":"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"}
1
+ {"version":3,"file":"HotkeyInput.mjs","names":["hotkeyMessages","useControlledState","modifiers: string[]","normalKeys: string[]","normalizedKey: any","Flexbox","Hotkey","ActionIcon"],"sources":["../../src/HotkeyInput/HotkeyInput.tsx"],"sourcesContent":["'use client';\n\nimport { type InputRef } from 'antd';\nimport { cx, useThemeMode } from 'antd-style';\nimport { isEqual } from 'es-toolkit/compat';\nimport { Undo2Icon, XIcon } from 'lucide-react';\nimport {\n type FocusEvent,\n memo,\n type MouseEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useHotkeys, useRecordHotkeys } from 'react-hotkeys-hook';\nimport useControlledState from 'use-merge-value';\n\nimport ActionIcon from '@/ActionIcon';\nimport { Flexbox } from '@/Flex';\nimport Hotkey from '@/Hotkey';\nimport { checkIsAppleDevice, NORMATIVE_MODIFIER, splitKeysByPlus } from '@/Hotkey/utils';\nimport hotkeyMessages from '@/i18n/resources/en/hotkey';\nimport { useTranslation } from '@/i18n/useTranslation';\n\nimport { styles, variants } from './style';\nimport { type HotkeyInputProps } from './type';\n\nconst HotkeyInput = memo<HotkeyInputProps>(\n ({\n value = '',\n defaultValue = '',\n resetValue = '',\n onChange,\n onClear,\n onConflict,\n placeholder,\n disabled,\n shadow,\n allowClear,\n allowReset = true,\n style,\n className,\n hotkeyConflicts = [],\n variant,\n texts,\n isApple,\n onBlur,\n onReset,\n onFocus,\n }) => {\n const [isFocused, setIsFocused] = useState(false);\n const [hasConflict, setHasConflict] = useState(false);\n const [hasInvalidCombination, setHasInvalidCombination] = useState(false);\n const inputRef = useRef<InputRef>(null);\n const { isDarkMode } = useThemeMode();\n const { t } = useTranslation(hotkeyMessages);\n const isAppleDevice = useMemo(() => checkIsAppleDevice(isApple), [isApple]);\n const [hotkeyValue, setHotkeyValue] = useControlledState(defaultValue, {\n defaultValue,\n onChange,\n value,\n });\n\n // 使用 useRecordHotkeys 处理快捷键录入\n const [recordedKeys, { start, stop, isRecording, resetKeys }] = useRecordHotkeys();\n\n useHotkeys(\n '*',\n () => {\n inputRef.current?.blur();\n },\n {\n enableOnContentEditable: true,\n enableOnFormTags: true,\n enabled: isRecording && !disabled,\n keydown: false,\n keyup: true,\n preventDefault: true,\n },\n );\n\n // 处理按键,保证格式正确:修饰键在前,最多一个非修饰键在后\n const formatKeys = useCallback((keysSet: Set<string>) => {\n const modifiers: string[] = [];\n const normalKeys: string[] = [];\n\n for (const key of keysSet) {\n // 处理不同表示的修饰键\n const normalizedKey: any = key.toLowerCase();\n if (NORMATIVE_MODIFIER.includes(normalizedKey)) {\n // 统一修饰键表示\n if (\n (!isAppleDevice && normalizedKey === 'ctrl') ||\n (isAppleDevice && normalizedKey === 'meta')\n ) {\n if (!modifiers.includes('mod')) modifiers.push('mod');\n } else if (!modifiers.includes(normalizedKey)) {\n modifiers.push(normalizedKey);\n }\n } else {\n normalKeys.push(key);\n }\n }\n\n // 至少需要一个修饰键\n if (modifiers.length === 0 && normalKeys.length > 0) {\n return { isValid: false, keys: [] };\n }\n\n // 只允许一个非修饰键,如果有多个,只保留最后一个\n const finalKey = normalKeys.length > 0 ? [normalKeys.at(-1)] : [];\n const shortcuts = [modifiers, finalKey];\n\n return {\n // 组合必须包含至少一个按键\n isValid: shortcuts.every((k) => k.length > 0),\n keys: shortcuts.flat(),\n };\n }, []);\n\n // 获取格式化后的按键字符串\n const { isValid, keys } = formatKeys(recordedKeys);\n const keysString = keys.join('+');\n\n // 检查快捷键冲突\n const checkHotkeyConflict = useCallback(\n (newHotkey: string): boolean => {\n return hotkeyConflicts\n .filter((conflictKey) => conflictKey !== resetValue)\n .some((conflictKey) => {\n const newKeys = splitKeysByPlus(newHotkey);\n const conflictKeys = splitKeysByPlus(conflictKey);\n return isEqual(newKeys, conflictKeys);\n });\n },\n [hotkeyConflicts],\n );\n\n // 当按键组合完成时处理结果\n useEffect(() => {\n if (recordedKeys.size > 0 && !isRecording) {\n if (!isValid) {\n setHasInvalidCombination(true);\n setHasConflict(false);\n return;\n }\n\n setHasInvalidCombination(false);\n const newKeysString = keysString;\n\n // 检查冲突\n const conflict = checkHotkeyConflict(newKeysString);\n if (conflict) {\n setHasConflict(true);\n onConflict?.(newKeysString);\n } else {\n setHasConflict(false);\n setHotkeyValue?.(newKeysString);\n }\n }\n }, [\n recordedKeys,\n isRecording,\n isValid,\n keysString,\n checkHotkeyConflict,\n setHotkeyValue,\n onConflict,\n ]);\n\n // 处理输入框焦点\n const handleFocus = (e: FocusEvent<HTMLInputElement>) => {\n if (disabled) return;\n setIsFocused(true);\n setHasConflict(false);\n setHasInvalidCombination(false);\n start(); // 开始记录\n onFocus?.(e);\n };\n\n const handleBlur = (e: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n stop(); // 停止记录\n onBlur?.(e);\n };\n\n const handleClear = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setHotkeyValue?.('');\n resetKeys();\n setHasConflict(false);\n setHasInvalidCombination(false);\n setIsFocused(false);\n stop();\n onClear?.(hotkeyValue);\n };\n\n // 重置功能\n const handleReset = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setHotkeyValue?.(resetValue);\n resetKeys();\n setHasConflict(false);\n setHasInvalidCombination(false);\n setIsFocused(false);\n stop(); // 停止记录\n onReset?.(hotkeyValue, resetValue);\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (disabled || isFocused) return;\n inputRef.current?.focus();\n };\n\n const placeholderText = placeholder ?? t('hotkey.placeholder');\n const resetTitle = texts?.reset ?? t('hotkey.reset');\n const clearTitle = texts?.clear ?? t('hotkey.clear');\n const conflictText = texts?.conflicts ?? t('hotkey.conflict');\n const invalidText = texts?.invalidCombination ?? t('hotkey.invalidCombination');\n\n return (\n <Flexbox\n className={className}\n gap={8}\n style={{\n position: 'relative',\n ...style,\n }}\n >\n <Flexbox\n horizontal\n align={'center'}\n justify={'space-between'}\n className={cx(\n variants({\n disabled,\n error: hasConflict || hasInvalidCombination,\n focused: isFocused,\n shadow,\n variant: variant || (isDarkMode ? 'filled' : 'outlined'),\n }),\n )}\n onClick={handleClick}\n >\n <div style={{ pointerEvents: 'none' }}>\n {isRecording ? (\n <span className={styles.placeholder}>\n {keys.length > 0 ? <Hotkey keys={keysString} /> : placeholderText}\n </span>\n ) : hotkeyValue ? (\n <Hotkey keys={hotkeyValue} />\n ) : (\n <span className={styles.placeholder}>{placeholderText}</span>\n )}\n </div>\n\n {/* 隐藏的输入框,用于接收焦点 */}\n <input\n readOnly\n className={styles.hiddenInput}\n disabled={disabled}\n ref={inputRef as any}\n style={{ pointerEvents: 'none' }}\n onBlur={handleBlur}\n onFocus={handleFocus}\n />\n\n {!isFocused && hotkeyValue && !disabled && (allowReset || allowClear) && (\n <Flexbox horizontal gap={4}>\n {allowReset && hotkeyValue !== resetValue && (\n <ActionIcon\n icon={Undo2Icon}\n size={'small'}\n title={resetTitle}\n variant={'filled'}\n onClick={handleReset}\n />\n )}\n {allowClear && (\n <ActionIcon\n icon={XIcon}\n size={'small'}\n title={clearTitle}\n variant={'filled'}\n onClick={handleClear}\n />\n )}\n </Flexbox>\n )}\n </Flexbox>\n {hasConflict && <div className={styles.errorText}>{conflictText}</div>}\n {hasInvalidCombination && <div className={styles.errorText}>{invalidText}</div>}\n </Flexbox>\n );\n },\n);\n\nHotkeyInput.displayName = 'HotkeyInput';\n\nexport default HotkeyInput;\n"],"mappings":"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"}
@@ -3,6 +3,7 @@ import { InputProps } from "antd";
3
3
 
4
4
  //#region src/HotkeyInput/type.d.ts
5
5
  interface HotkeyInputProps {
6
+ allowClear?: boolean;
6
7
  allowReset?: boolean;
7
8
  className?: string;
8
9
  defaultValue?: string;
@@ -11,6 +12,7 @@ interface HotkeyInputProps {
11
12
  isApple?: boolean;
12
13
  onBlur?: InputProps['onBlur'];
13
14
  onChange?: (value: string) => void;
15
+ onClear?: (currentValue: string) => void;
14
16
  onConflict?: (conflictKey: string) => void;
15
17
  onFocus?: InputProps['onFocus'];
16
18
  onReset?: (currentValue: string, resetValue: string) => void;
@@ -19,6 +21,7 @@ interface HotkeyInputProps {
19
21
  shadow?: boolean;
20
22
  style?: CSSProperties;
21
23
  texts?: {
24
+ clear?: string;
22
25
  conflicts?: string;
23
26
  invalidCombination?: string;
24
27
  reset?: string;
@@ -1,8 +1,8 @@
1
1
  import { IconProps } from "./type.mjs";
2
- import * as react67 from "react";
2
+ import * as react25 from "react";
3
3
 
4
4
  //#region src/Icon/Icon.d.ts
5
- declare const Icon: react67.NamedExoticComponent<IconProps>;
5
+ declare const Icon: react25.NamedExoticComponent<IconProps>;
6
6
  //#endregion
7
7
  export { Icon };
8
8
  //# sourceMappingURL=Icon.d.mts.map
@@ -1,11 +1,11 @@
1
1
  import { IconProps } from "../type.mjs";
2
- import * as react65 from "react";
2
+ import * as react23 from "react";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/Icon/components/IconProvider.d.ts
6
6
  type IconContentConfig = Omit<IconProps, 'icon' | 'ref'>;
7
- declare const IconContext: react65.Context<IconContentConfig>;
8
- declare const IconProvider: react65.NamedExoticComponent<{
7
+ declare const IconContext: react23.Context<IconContentConfig>;
8
+ declare const IconProvider: react23.NamedExoticComponent<{
9
9
  children: ReactNode;
10
10
  config?: IconContentConfig;
11
11
  }>;
@@ -12,7 +12,7 @@ import { cssVar, cx, useThemeMode } from "antd-style";
12
12
  const Image$1 = memo(({ ref, style, preview, isLoading, maxHeight = "100%", maxWidth = "100%", minHeight, minWidth, actions, className, alwaysShowActions, variant = "filled", objectFit = "cover", classNames, styles: customStyles, onClick, width, height, ...rest }) => {
13
13
  const { isDarkMode } = useThemeMode();
14
14
  const actionsClassName = alwaysShowActions ? styles.actionsVisible : styles.actionsHidden;
15
- const mergePreivew = usePreview_default(preview);
15
+ const mergePreview = usePreview_default(preview);
16
16
  if (isLoading) return /* @__PURE__ */ jsx("div", {
17
17
  onClick,
18
18
  children: /* @__PURE__ */ jsx(Skeleton.Avatar, {
@@ -40,7 +40,7 @@ const Image$1 = memo(({ ref, style, preview, isLoading, maxHeight = "100%", maxW
40
40
  fallback: isDarkMode ? FALLBACK_DARK : FALLBACK_LIGHT,
41
41
  height,
42
42
  loading: "lazy",
43
- preview: preview === false ? false : mergePreivew,
43
+ preview: preview === false ? false : mergePreview,
44
44
  width,
45
45
  classNames: { root: cx(styles.wrapper, classNames?.wrapper) },
46
46
  style: {
@@ -1 +1 @@
1
- {"version":3,"file":"Image.mjs","names":["Image","usePreview","Flexbox","AntImage"],"sources":["../../src/Image/Image.tsx"],"sourcesContent":["'use client';\n\nimport { Image as AntImage, Skeleton } from 'antd';\nimport { cssVar, cx, useThemeMode } from 'antd-style';\nimport { memo } from 'react';\n\nimport { Flexbox } from '@/Flex';\n\nimport usePreview from './components/usePreview';\nimport { FALLBACK_DARK, FALLBACK_LIGHT, styles, variants } from './style';\nimport type { ImageProps } from './type';\n\nconst Image = memo<ImageProps>(\n ({\n ref,\n style,\n preview,\n isLoading,\n maxHeight = '100%',\n maxWidth = '100%',\n minHeight,\n minWidth,\n actions,\n className,\n alwaysShowActions,\n variant = 'filled',\n objectFit = 'cover',\n classNames,\n styles: customStyles,\n onClick,\n width,\n height,\n ...rest\n }) => {\n const { isDarkMode } = useThemeMode();\n const actionsClassName = alwaysShowActions ? styles.actionsVisible : styles.actionsHidden;\n const mergePreivew = usePreview(preview);\n\n if (isLoading)\n return (\n <div onClick={onClick}>\n <Skeleton.Avatar\n active\n style={{\n borderRadius: cssVar.borderRadius,\n height,\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n width,\n }}\n />\n </div>\n );\n\n return (\n <Flexbox className={cx(variants({ variant }), className)} ref={ref} style={style}>\n {actions && (\n <div className={cx(actionsClassName, alwaysShowActions ? '' : 'actions-hidden')}>\n {actions}\n </div>\n )}\n <AntImage\n className={cx(styles.image, classNames?.image)}\n fallback={isDarkMode ? FALLBACK_DARK : FALLBACK_LIGHT}\n height={height}\n loading={'lazy'}\n preview={preview === false ? false : (mergePreivew as any)}\n width={width}\n classNames={{\n root: cx(styles.wrapper, classNames?.wrapper),\n }}\n style={{\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n objectFit: objectFit || 'cover',\n ...customStyles?.image,\n }}\n styles={{\n root: customStyles?.wrapper,\n }}\n onClick={onClick}\n {...rest}\n />\n </Flexbox>\n );\n },\n);\n\nImage.displayName = 'Image';\n\nexport default Image;\n"],"mappings":";;;;;;;;;;;AAYA,MAAMA,UAAQ,MACX,EACC,KACA,OACA,SACA,WACA,YAAY,QACZ,WAAW,QACX,WACA,UACA,SACA,WACA,mBACA,UAAU,UACV,YAAY,SACZ,YACA,QAAQ,cACR,SACA,OACA,QACA,GAAG,WACC;CACJ,MAAM,EAAE,eAAe,cAAc;CACrC,MAAM,mBAAmB,oBAAoB,OAAO,iBAAiB,OAAO;CAC5E,MAAM,eAAeC,mBAAW,QAAQ;AAExC,KAAI,UACF,QACE,oBAAC;EAAa;YACZ,oBAAC,SAAS;GACR;GACA,OAAO;IACL,cAAc,OAAO;IACrB;IACA;IACA;IACA;IACA;IACA;IACD;IACD;GACE;AAGV,QACE,qBAACC;EAAQ,WAAW,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,UAAU;EAAO;EAAY;aACxE,WACC,oBAAC;GAAI,WAAW,GAAG,kBAAkB,oBAAoB,KAAK,iBAAiB;aAC5E;IACG,EAER,oBAACC;GACC,WAAW,GAAG,OAAO,OAAO,YAAY,MAAM;GAC9C,UAAU,aAAa,gBAAgB;GAC/B;GACR,SAAS;GACT,SAAS,YAAY,QAAQ,QAAS;GAC/B;GACP,YAAY,EACV,MAAM,GAAG,OAAO,SAAS,YAAY,QAAQ,EAC9C;GACD,OAAO;IACL;IACA;IACA;IACA;IACA,WAAW,aAAa;IACxB,GAAG,cAAc;IAClB;GACD,QAAQ,EACN,MAAM,cAAc,SACrB;GACQ;GACT,GAAI;IACJ;GACM;EAGf;AAED,QAAM,cAAc;AAEpB,oBAAeH"}
1
+ {"version":3,"file":"Image.mjs","names":["Image","usePreview","Flexbox","AntImage"],"sources":["../../src/Image/Image.tsx"],"sourcesContent":["'use client';\n\nimport { Image as AntImage, Skeleton } from 'antd';\nimport { cssVar, cx, useThemeMode } from 'antd-style';\nimport { memo } from 'react';\n\nimport { Flexbox } from '@/Flex';\n\nimport usePreview from './components/usePreview';\nimport { FALLBACK_DARK, FALLBACK_LIGHT, styles, variants } from './style';\nimport type { ImageProps } from './type';\n\nconst Image = memo<ImageProps>(\n ({\n ref,\n style,\n preview,\n isLoading,\n maxHeight = '100%',\n maxWidth = '100%',\n minHeight,\n minWidth,\n actions,\n className,\n alwaysShowActions,\n variant = 'filled',\n objectFit = 'cover',\n classNames,\n styles: customStyles,\n onClick,\n width,\n height,\n ...rest\n }) => {\n const { isDarkMode } = useThemeMode();\n const actionsClassName = alwaysShowActions ? styles.actionsVisible : styles.actionsHidden;\n const mergePreview = usePreview(preview);\n\n if (isLoading)\n return (\n <div onClick={onClick}>\n <Skeleton.Avatar\n active\n style={{\n borderRadius: cssVar.borderRadius,\n height,\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n width,\n }}\n />\n </div>\n );\n\n return (\n <Flexbox className={cx(variants({ variant }), className)} ref={ref} style={style}>\n {actions && (\n <div className={cx(actionsClassName, alwaysShowActions ? '' : 'actions-hidden')}>\n {actions}\n </div>\n )}\n <AntImage\n className={cx(styles.image, classNames?.image)}\n fallback={isDarkMode ? FALLBACK_DARK : FALLBACK_LIGHT}\n height={height}\n loading={'lazy'}\n preview={preview === false ? false : (mergePreview as any)}\n width={width}\n classNames={{\n root: cx(styles.wrapper, classNames?.wrapper),\n }}\n style={{\n maxHeight,\n maxWidth,\n minHeight,\n minWidth,\n objectFit: objectFit || 'cover',\n ...customStyles?.image,\n }}\n styles={{\n root: customStyles?.wrapper,\n }}\n onClick={onClick}\n {...rest}\n />\n </Flexbox>\n );\n },\n);\n\nImage.displayName = 'Image';\n\nexport default Image;\n"],"mappings":";;;;;;;;;;;AAYA,MAAMA,UAAQ,MACX,EACC,KACA,OACA,SACA,WACA,YAAY,QACZ,WAAW,QACX,WACA,UACA,SACA,WACA,mBACA,UAAU,UACV,YAAY,SACZ,YACA,QAAQ,cACR,SACA,OACA,QACA,GAAG,WACC;CACJ,MAAM,EAAE,eAAe,cAAc;CACrC,MAAM,mBAAmB,oBAAoB,OAAO,iBAAiB,OAAO;CAC5E,MAAM,eAAeC,mBAAW,QAAQ;AAExC,KAAI,UACF,QACE,oBAAC;EAAa;YACZ,oBAAC,SAAS;GACR;GACA,OAAO;IACL,cAAc,OAAO;IACrB;IACA;IACA;IACA;IACA;IACA;IACD;IACD;GACE;AAGV,QACE,qBAACC;EAAQ,WAAW,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,UAAU;EAAO;EAAY;aACxE,WACC,oBAAC;GAAI,WAAW,GAAG,kBAAkB,oBAAoB,KAAK,iBAAiB;aAC5E;IACG,EAER,oBAACC;GACC,WAAW,GAAG,OAAO,OAAO,YAAY,MAAM;GAC9C,UAAU,aAAa,gBAAgB;GAC/B;GACR,SAAS;GACT,SAAS,YAAY,QAAQ,QAAS;GAC/B;GACP,YAAY,EACV,MAAM,GAAG,OAAO,SAAS,YAAY,QAAQ,EAC9C;GACD,OAAO;IACL;IACA;IACA;IACA;IACA,WAAW,aAAa;IACxB,GAAG,cAAc;IAClB;GACD,QAAQ,EACN,MAAM,cAAc,SACrB;GACQ;GACT,GAAI;IACJ;GACM;EAGf;AAED,QAAM,cAAc;AAEpB,oBAAeH"}
@@ -1,8 +1,8 @@
1
1
  import { PreviewGroupProps } from "./type.mjs";
2
- import * as react58 from "react";
2
+ import * as react35 from "react";
3
3
 
4
4
  //#region src/Image/PreviewGroup.d.ts
5
- declare const PreviewGroup: react58.NamedExoticComponent<PreviewGroupProps>;
5
+ declare const PreviewGroup: react35.NamedExoticComponent<PreviewGroupProps>;
6
6
  //#endregion
7
7
  export { PreviewGroup };
8
8
  //# sourceMappingURL=PreviewGroup.d.mts.map
@@ -1,46 +1,126 @@
1
1
  import FlexBasic_default from "../../Flex/FlexBasic.mjs";
2
+ import TooltipGroup_default from "../../Tooltip/TooltipGroup.mjs";
2
3
  import ActionIcon_default from "../../ActionIcon/ActionIcon.mjs";
4
+ import { useTranslation } from "../../i18n/useTranslation.mjs";
5
+ import { downloadBlob } from "../../utils/downloadBlob.mjs";
3
6
  import { styles } from "../style.mjs";
4
- import { memo } from "react";
7
+ import image_default from "../../i18n/resources/en/image.mjs";
8
+ import { getClipboardBlob } from "../../utils/blobToPng.mjs";
9
+ import { memo, useCallback, useState } from "react";
5
10
  import { jsx, jsxs } from "react/jsx-runtime";
6
- import { FlipHorizontal, FlipVertical, RotateCcw, RotateCw, ZoomIn, ZoomOut } from "lucide-react";
11
+ import { message } from "antd";
12
+ import { Copy, Download, FlipHorizontal, FlipVertical, RotateCcw, RotateCw, ZoomIn, ZoomOut } from "lucide-react";
7
13
 
8
14
  //#region src/Image/components/Toolbar.tsx
15
+ const getFileNameFromUrl = (url) => {
16
+ try {
17
+ const match = new URL(url).pathname.match(/\/([^/]+)$/);
18
+ return match ? decodeURIComponent(match[1]) : "image";
19
+ } catch {
20
+ return "image";
21
+ }
22
+ };
23
+ const getExtensionFromMimeType = (mimeType) => {
24
+ return {
25
+ "image/svg+xml": "svg",
26
+ "image/png": "png",
27
+ "image/jpeg": "jpg",
28
+ "image/jpg": "jpg",
29
+ "image/webp": "webp",
30
+ "image/gif": "gif"
31
+ }[mimeType?.toLowerCase()] || mimeType?.split("/")[1]?.split("+")[0] || "png";
32
+ };
9
33
  const Toolbar = memo(({ children, info, minScale, maxScale }) => {
10
- const { transform: { scale }, actions: { onFlipY, onFlipX, onRotateLeft, onRotateRight, onZoomOut, onZoomIn } } = info;
11
- return /* @__PURE__ */ jsxs(FlexBasic_default, {
12
- horizontal: true,
13
- className: styles.toolbar,
14
- gap: 4,
15
- children: [
16
- /* @__PURE__ */ jsx(ActionIcon_default, {
17
- icon: FlipHorizontal,
18
- onClick: onFlipX
19
- }),
20
- /* @__PURE__ */ jsx(ActionIcon_default, {
21
- icon: FlipVertical,
22
- onClick: onFlipY
23
- }),
24
- /* @__PURE__ */ jsx(ActionIcon_default, {
25
- icon: RotateCcw,
26
- onClick: onRotateLeft
27
- }),
28
- /* @__PURE__ */ jsx(ActionIcon_default, {
29
- icon: RotateCw,
30
- onClick: onRotateRight
31
- }),
32
- /* @__PURE__ */ jsx(ActionIcon_default, {
33
- disabled: scale === minScale,
34
- icon: ZoomOut,
35
- onClick: onZoomOut
36
- }),
37
- /* @__PURE__ */ jsx(ActionIcon_default, {
38
- disabled: scale === maxScale,
39
- icon: ZoomIn,
40
- onClick: onZoomIn
41
- }),
42
- children
43
- ]
34
+ const { t } = useTranslation(image_default);
35
+ const [containerEl, setContainerEl] = useState(null);
36
+ const [copyLoading, setCopyLoading] = useState(false);
37
+ const [downloadLoading, setDownloadLoading] = useState(false);
38
+ const { transform: { scale }, actions: { onFlipY, onFlipX, onRotateLeft, onRotateRight, onZoomOut, onZoomIn }, image: { url } } = info;
39
+ const handleDownload = useCallback(async () => {
40
+ setDownloadLoading(true);
41
+ try {
42
+ const blob = await (await fetch(url, { mode: "cors" })).blob();
43
+ const blobUrl = URL.createObjectURL(blob);
44
+ let fileName = getFileNameFromUrl(url);
45
+ const ext = getExtensionFromMimeType(blob.type);
46
+ if (!fileName.includes(".")) fileName = `${fileName}.${ext}`;
47
+ else if (fileName.endsWith(".svg+xml")) fileName = fileName.replace(/\.svg\+xml$/i, ".svg");
48
+ await downloadBlob(blobUrl, fileName);
49
+ URL.revokeObjectURL(blobUrl);
50
+ message.success(t("image.downloadSuccess"));
51
+ } catch {
52
+ message.error(t("image.downloadFailed"));
53
+ } finally {
54
+ setDownloadLoading(false);
55
+ }
56
+ }, [url, t]);
57
+ const handleCopy = useCallback(async () => {
58
+ setCopyLoading(true);
59
+ try {
60
+ const clipboardBlob = await getClipboardBlob(await (await fetch(url, { mode: "cors" })).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_default, {
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_default, {
78
+ icon: FlipHorizontal,
79
+ title: t("image.flipHorizontal"),
80
+ onClick: onFlipX
81
+ }),
82
+ /* @__PURE__ */ jsx(ActionIcon_default, {
83
+ icon: FlipVertical,
84
+ title: t("image.flipVertical"),
85
+ onClick: onFlipY
86
+ }),
87
+ /* @__PURE__ */ jsx(ActionIcon_default, {
88
+ icon: RotateCcw,
89
+ title: t("image.rotateLeft"),
90
+ onClick: onRotateLeft
91
+ }),
92
+ /* @__PURE__ */ jsx(ActionIcon_default, {
93
+ icon: RotateCw,
94
+ title: t("image.rotateRight"),
95
+ onClick: onRotateRight
96
+ }),
97
+ /* @__PURE__ */ jsx(ActionIcon_default, {
98
+ disabled: scale === minScale,
99
+ icon: ZoomOut,
100
+ title: t("image.zoomOut"),
101
+ onClick: onZoomOut
102
+ }),
103
+ /* @__PURE__ */ jsx(ActionIcon_default, {
104
+ disabled: scale === maxScale,
105
+ icon: ZoomIn,
106
+ title: t("image.zoomIn"),
107
+ onClick: onZoomIn
108
+ }),
109
+ /* @__PURE__ */ jsx(ActionIcon_default, {
110
+ icon: Copy,
111
+ loading: copyLoading,
112
+ title: t("image.copy"),
113
+ onClick: handleCopy
114
+ }),
115
+ /* @__PURE__ */ jsx(ActionIcon_default, {
116
+ icon: Download,
117
+ loading: downloadLoading,
118
+ title: t("image.download"),
119
+ onClick: handleDownload
120
+ }),
121
+ children
122
+ ]
123
+ })
44
124
  });
45
125
  });
46
126
  var Toolbar_default = Toolbar;
@@ -1 +1 @@
1
- {"version":3,"file":"Toolbar.mjs","names":["Flexbox","ActionIcon"],"sources":["../../../src/Image/components/Toolbar.tsx"],"sourcesContent":["import { FlipHorizontal, FlipVertical, RotateCcw, RotateCw, ZoomIn, ZoomOut } from 'lucide-react';\nimport { type ToolbarRenderInfoType } from 'rc-image/lib/Preview';\nimport { memo, type ReactNode } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport { Flexbox } from '@/Flex';\n\nimport { styles } from '../style';\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 {\n transform: { scale },\n actions: { onFlipY, onFlipX, onRotateLeft, onRotateRight, onZoomOut, onZoomIn },\n } = info;\n\n return (\n <Flexbox horizontal className={styles.toolbar} gap={4}>\n <ActionIcon icon={FlipHorizontal} onClick={onFlipX} />\n <ActionIcon icon={FlipVertical} onClick={onFlipY} />\n <ActionIcon icon={RotateCcw} onClick={onRotateLeft} />\n <ActionIcon icon={RotateCw} onClick={onRotateRight} />\n <ActionIcon disabled={scale === minScale} icon={ZoomOut} onClick={onZoomOut} />\n <ActionIcon disabled={scale === maxScale} icon={ZoomIn} onClick={onZoomIn} />\n {children}\n </Flexbox>\n );\n});\n\nexport default Toolbar;\n"],"mappings":";;;;;;;;AAgBA,MAAM,UAAU,MAAoB,EAAE,UAAU,MAAM,UAAU,eAAe;CAC7E,MAAM,EACJ,WAAW,EAAE,SACb,SAAS,EAAE,SAAS,SAAS,cAAc,eAAe,WAAW,eACnE;AAEJ,QACE,qBAACA;EAAQ;EAAW,WAAW,OAAO;EAAS,KAAK;;GAClD,oBAACC;IAAW,MAAM;IAAgB,SAAS;KAAW;GACtD,oBAACA;IAAW,MAAM;IAAc,SAAS;KAAW;GACpD,oBAACA;IAAW,MAAM;IAAW,SAAS;KAAgB;GACtD,oBAACA;IAAW,MAAM;IAAU,SAAS;KAAiB;GACtD,oBAACA;IAAW,UAAU,UAAU;IAAU,MAAM;IAAS,SAAS;KAAa;GAC/E,oBAACA;IAAW,UAAU,UAAU;IAAU,MAAM;IAAQ,SAAS;KAAY;GAC5E;;GACO;EAEZ;AAEF,sBAAe"}
1
+ {"version":3,"file":"Toolbar.mjs","names":["imageMessages","TooltipGroup","Flexbox","ActionIcon"],"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,8 +1,8 @@
1
1
  import { InputProps } from "./type.mjs";
2
- import * as react150 from "react";
2
+ import * as react153 from "react";
3
3
 
4
4
  //#region src/Input/Input.d.ts
5
- declare const Input: react150.NamedExoticComponent<InputProps>;
5
+ declare const Input: react153.NamedExoticComponent<InputProps>;
6
6
  //#endregion
7
7
  export { Input };
8
8
  //# sourceMappingURL=Input.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { InputOPTProps } from "./type.mjs";
2
- import * as react152 from "react";
2
+ import * as react155 from "react";
3
3
 
4
4
  //#region src/Input/InputOPT.d.ts
5
- declare const InputOPT: react152.NamedExoticComponent<InputOPTProps>;
5
+ declare const InputOPT: react155.NamedExoticComponent<InputOPTProps>;
6
6
  //#endregion
7
7
  export { InputOPT };
8
8
  //# sourceMappingURL=InputOPT.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { InputPasswordProps } from "./type.mjs";
2
- import * as react151 from "react";
2
+ import * as react156 from "react";
3
3
 
4
4
  //#region src/Input/InputPassword.d.ts
5
- declare const InputPassword: react151.NamedExoticComponent<InputPasswordProps>;
5
+ declare const InputPassword: react156.NamedExoticComponent<InputPasswordProps>;
6
6
  //#endregion
7
7
  export { InputPassword };
8
8
  //# sourceMappingURL=InputPassword.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { TextAreaProps } from "./type.mjs";
2
- import * as react153 from "react";
2
+ import * as react157 from "react";
3
3
 
4
4
  //#region src/Input/TextArea.d.ts
5
- declare const TextArea: react153.NamedExoticComponent<TextAreaProps>;
5
+ declare const TextArea: react157.NamedExoticComponent<TextAreaProps>;
6
6
  //#endregion
7
7
  export { TextArea };
8
8
  //# sourceMappingURL=TextArea.d.mts.map
@@ -1,9 +1,9 @@
1
1
  import { DivProps } from "../../types/index.mjs";
2
2
  import "../../index.mjs";
3
- import * as react63 from "react";
3
+ import * as react28 from "react";
4
4
 
5
5
  //#region src/Layout/components/LayoutFooter.d.ts
6
- declare const LayoutFooter: react63.NamedExoticComponent<DivProps>;
6
+ declare const LayoutFooter: react28.NamedExoticComponent<DivProps>;
7
7
  //#endregion
8
8
  export { LayoutFooter };
9
9
  //# sourceMappingURL=LayoutFooter.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { LayoutHeaderProps } from "../type.mjs";
2
- import * as react64 from "react";
2
+ import * as react29 from "react";
3
3
 
4
4
  //#region src/Layout/components/LayoutHeader.d.ts
5
- declare const LayoutHeader: react64.NamedExoticComponent<LayoutHeaderProps>;
5
+ declare const LayoutHeader: react29.NamedExoticComponent<LayoutHeaderProps>;
6
6
  //#endregion
7
7
  export { LayoutHeader };
8
8
  //# sourceMappingURL=LayoutHeader.d.mts.map
@@ -1,9 +1,9 @@
1
1
  import { DivProps } from "../../types/index.mjs";
2
2
  import "../../index.mjs";
3
- import * as react59 from "react";
3
+ import * as react30 from "react";
4
4
 
5
5
  //#region src/Layout/components/LayoutMain.d.ts
6
- declare const LayoutMain: react59.NamedExoticComponent<DivProps>;
6
+ declare const LayoutMain: react30.NamedExoticComponent<DivProps>;
7
7
  //#endregion
8
8
  export { LayoutMain };
9
9
  //# sourceMappingURL=LayoutMain.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { LayoutSidebarProps } from "../type.mjs";
2
- import * as react60 from "react";
2
+ import * as react31 from "react";
3
3
 
4
4
  //#region src/Layout/components/LayoutSidebar.d.ts
5
- declare const LayoutSidebar: react60.NamedExoticComponent<LayoutSidebarProps>;
5
+ declare const LayoutSidebar: react31.NamedExoticComponent<LayoutSidebarProps>;
6
6
  //#endregion
7
7
  export { LayoutSidebar };
8
8
  //# sourceMappingURL=LayoutSidebar.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { LayoutSidebarInnerProps } from "../type.mjs";
2
- import * as react61 from "react";
2
+ import * as react32 from "react";
3
3
 
4
4
  //#region src/Layout/components/LayoutSidebarInner.d.ts
5
- declare const LayoutSidebarInner: react61.NamedExoticComponent<LayoutSidebarInnerProps>;
5
+ declare const LayoutSidebarInner: react32.NamedExoticComponent<LayoutSidebarInnerProps>;
6
6
  //#endregion
7
7
  export { LayoutSidebarInner };
8
8
  //# sourceMappingURL=LayoutSidebarInner.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { LayoutTocProps } from "../type.mjs";
2
- import * as react62 from "react";
2
+ import * as react33 from "react";
3
3
 
4
4
  //#region src/Layout/components/LayoutToc.d.ts
5
- declare const LayoutToc: react62.NamedExoticComponent<LayoutTocProps>;
5
+ declare const LayoutToc: react33.NamedExoticComponent<LayoutTocProps>;
6
6
  //#endregion
7
7
  export { LayoutToc };
8
8
  //# sourceMappingURL=LayoutToc.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { ListItemProps } from "../type.mjs";
2
- import * as react72 from "react";
2
+ import * as react27 from "react";
3
3
 
4
4
  //#region src/List/ListItem/index.d.ts
5
- declare const ListItem: react72.NamedExoticComponent<ListItemProps>;
5
+ declare const ListItem: react27.NamedExoticComponent<ListItemProps>;
6
6
  //#endregion
7
7
  export { ListItem };
8
8
  //# sourceMappingURL=index.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { MarkdownProps } from "./type.mjs";
2
- import * as react53 from "react";
2
+ import * as react37 from "react";
3
3
 
4
4
  //#region src/Markdown/Markdown.d.ts
5
- declare const Markdown: react53.NamedExoticComponent<MarkdownProps>;
5
+ declare const Markdown: react37.NamedExoticComponent<MarkdownProps>;
6
6
  //#endregion
7
7
  export { Markdown };
8
8
  //# sourceMappingURL=Markdown.d.mts.map
@@ -13,7 +13,7 @@ import { cx } from "antd-style";
13
13
 
14
14
  //#region src/Markdown/Markdown.tsx
15
15
  const Markdown = memo((props) => {
16
- const { ref, children = "", className, style, fullFeaturedCodeBlock, onDoubleClick, animated, enableLatex = true, enableMermaid = true, enableImageGallery, enableCustomFootnotes, enableGithubAlert, enableStream = true, componentProps, rehypePluginsAhead, allowHtml, borderRadius, fontSize = props.variant === "chat" ? 14 : void 0, headerMultiple = props.variant === "chat" ? .25 : void 0, marginMultiple = props.variant === "chat" ? 1 : void 0, variant = "default", reactMarkdownProps, lineHeight = props.variant === "chat" ? 1.6 : void 0, rehypePlugins, remarkPlugins, remarkPluginsAhead, components = {}, customRender, showFootnotes = true, citations, ...rest } = props;
16
+ const { ref, children = "", className, style, fullFeaturedCodeBlock, onDoubleClick, animated, enableLatex = true, enableMermaid = true, enableImageGallery, enableCustomFootnotes, enableGithubAlert, enableStream = true, componentProps, rehypePluginsAhead, allowHtml, borderRadius, fontSize = props.variant === "chat" ? 14 : void 0, headerMultiple = props.variant === "chat" ? .25 : void 0, marginMultiple = props.variant === "chat" ? 1 : void 0, variant = "default", reactMarkdownProps, lineHeight = props.variant === "chat" ? 1.6 : void 0, rehypePlugins, remarkPlugins, remarkPluginsAhead, components = {}, customRender, showFootnotes = true, streamSmoothingPreset, citations, ...rest } = props;
17
17
  const delayedAnimated = useDelayedAnimated(animated);
18
18
  const Render = useCallback(({ enableStream: enableStream$1, children: children$1, reactMarkdownProps: reactMarkdownProps$1 }) => {
19
19
  const defaultDOM = /* @__PURE__ */ jsx(enableStream$1 ? StreamdownRender_default : MarkdownRender_default, {
@@ -55,6 +55,7 @@ const Markdown = memo((props) => {
55
55
  remarkPlugins,
56
56
  remarkPluginsAhead,
57
57
  showFootnotes,
58
+ streamSmoothingPreset,
58
59
  variant,
59
60
  children: /* @__PURE__ */ jsx(Render, {
60
61
  enableStream: enableStream && delayedAnimated,
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.mjs","names":["enableStream","StreamdownRender","MarkdownRender","reactMarkdownProps","children","PreviewGroup","Typography"],"sources":["../../src/Markdown/Markdown.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { memo, useCallback } from 'react';\n\nimport { PreviewGroup } from '@/Image';\n\nimport { MarkdownProvider } from './components/MarkdownProvider';\nimport { useDelayedAnimated } from './components/useDelayedAnimated';\nimport { variants } from './style';\nimport { MarkdownRender, StreamdownRender } from './SyntaxMarkdown';\nimport { type MarkdownProps } from './type';\nimport Typography from './Typography';\n\nconst Markdown = memo<MarkdownProps>((props) => {\n const {\n ref,\n children = '',\n className,\n style,\n fullFeaturedCodeBlock,\n onDoubleClick,\n animated,\n enableLatex = true,\n enableMermaid = true,\n enableImageGallery,\n enableCustomFootnotes,\n enableGithubAlert,\n enableStream = true,\n componentProps,\n rehypePluginsAhead,\n allowHtml,\n borderRadius,\n fontSize = props.variant === 'chat' ? 14 : undefined,\n headerMultiple = props.variant === 'chat' ? 0.25 : undefined,\n marginMultiple = props.variant === 'chat' ? 1 : undefined,\n variant = 'default',\n reactMarkdownProps,\n lineHeight = props.variant === 'chat' ? 1.6 : undefined,\n rehypePlugins,\n remarkPlugins,\n remarkPluginsAhead,\n components = {},\n customRender,\n showFootnotes = true,\n citations,\n ...rest\n } = props;\n\n const delayedAnimated = useDelayedAnimated(animated);\n\n const Render = useCallback(\n ({\n enableStream,\n children,\n reactMarkdownProps,\n }: Pick<MarkdownProps, 'children' | 'enableStream' | 'reactMarkdownProps'>) => {\n const DefaultRender = enableStream ? StreamdownRender : MarkdownRender;\n const defaultDOM = <DefaultRender {...reactMarkdownProps}>{children}</DefaultRender>;\n return customRender ? customRender(defaultDOM, { text: children }) : defaultDOM;\n },\n [customRender],\n );\n\n return (\n <PreviewGroup enable={enableImageGallery}>\n <Typography\n borderRadius={borderRadius}\n className={cx(variants({ enableLatex, variant }), className)}\n data-code-type=\"markdown\"\n fontSize={fontSize}\n headerMultiple={headerMultiple}\n lineHeight={lineHeight}\n marginMultiple={marginMultiple}\n ref={ref}\n style={style}\n onDoubleClick={onDoubleClick}\n {...rest}\n >\n <MarkdownProvider\n allowHtml={allowHtml}\n animated={delayedAnimated}\n citations={citations}\n componentProps={componentProps}\n components={components}\n enableCustomFootnotes={enableCustomFootnotes}\n enableGithubAlert={enableGithubAlert}\n enableLatex={enableLatex}\n enableMermaid={enableMermaid}\n fullFeaturedCodeBlock={fullFeaturedCodeBlock}\n rehypePlugins={rehypePlugins}\n rehypePluginsAhead={rehypePluginsAhead}\n remarkPlugins={remarkPlugins}\n remarkPluginsAhead={remarkPluginsAhead}\n showFootnotes={showFootnotes}\n variant={variant}\n >\n <Render\n enableStream={enableStream && delayedAnimated}\n reactMarkdownProps={reactMarkdownProps}\n >\n {children}\n </Render>\n </MarkdownProvider>\n </Typography>\n </PreviewGroup>\n );\n});\n\nMarkdown.displayName = 'Markdown';\n\nexport default Markdown;\n"],"mappings":";;;;;;;;;;;;;;AAcA,MAAM,WAAW,MAAqB,UAAU;CAC9C,MAAM,EACJ,KACA,WAAW,IACX,WACA,OACA,uBACA,eACA,UACA,cAAc,MACd,gBAAgB,MAChB,oBACA,uBACA,mBACA,eAAe,MACf,gBACA,oBACA,WACA,cACA,WAAW,MAAM,YAAY,SAAS,KAAK,QAC3C,iBAAiB,MAAM,YAAY,SAAS,MAAO,QACnD,iBAAiB,MAAM,YAAY,SAAS,IAAI,QAChD,UAAU,WACV,oBACA,aAAa,MAAM,YAAY,SAAS,MAAM,QAC9C,eACA,eACA,oBACA,aAAa,EAAE,EACf,cACA,gBAAgB,MAChB,WACA,GAAG,SACD;CAEJ,MAAM,kBAAkB,mBAAmB,SAAS;CAEpD,MAAM,SAAS,aACZ,EACC,8BACA,sBACA,+CAC6E;EAE7E,MAAM,aAAa,oBADGA,iBAAeC,2BAAmBC;GACtB,GAAIC;aAAqBC;IAAyB;AACpF,SAAO,eAAe,aAAa,YAAY,EAAE,MAAMA,YAAU,CAAC,GAAG;IAEvE,CAAC,aAAa,CACf;AAED,QACE,oBAACC;EAAa,QAAQ;YACpB,oBAACC;GACe;GACd,WAAW,GAAG,SAAS;IAAE;IAAa;IAAS,CAAC,EAAE,UAAU;GAC5D,kBAAe;GACL;GACM;GACJ;GACI;GACX;GACE;GACQ;GACf,GAAI;aAEJ,oBAAC;IACY;IACX,UAAU;IACC;IACK;IACJ;IACW;IACJ;IACN;IACE;IACQ;IACR;IACK;IACL;IACK;IACL;IACN;cAET,oBAAC;KACC,cAAc,gBAAgB;KACV;KAEnB;MACM;KACQ;IACR;GACA;EAEjB;AAEF,SAAS,cAAc;AAEvB,uBAAe"}
1
+ {"version":3,"file":"Markdown.mjs","names":["enableStream","StreamdownRender","MarkdownRender","reactMarkdownProps","children","PreviewGroup","Typography"],"sources":["../../src/Markdown/Markdown.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { memo, useCallback } from 'react';\n\nimport { PreviewGroup } from '@/Image';\n\nimport { MarkdownProvider } from './components/MarkdownProvider';\nimport { useDelayedAnimated } from './components/useDelayedAnimated';\nimport { variants } from './style';\nimport { MarkdownRender, StreamdownRender } from './SyntaxMarkdown';\nimport { type MarkdownProps } from './type';\nimport Typography from './Typography';\n\nconst Markdown = memo<MarkdownProps>((props) => {\n const {\n ref,\n children = '',\n className,\n style,\n fullFeaturedCodeBlock,\n onDoubleClick,\n animated,\n enableLatex = true,\n enableMermaid = true,\n enableImageGallery,\n enableCustomFootnotes,\n enableGithubAlert,\n enableStream = true,\n componentProps,\n rehypePluginsAhead,\n allowHtml,\n borderRadius,\n fontSize = props.variant === 'chat' ? 14 : undefined,\n headerMultiple = props.variant === 'chat' ? 0.25 : undefined,\n marginMultiple = props.variant === 'chat' ? 1 : undefined,\n variant = 'default',\n reactMarkdownProps,\n lineHeight = props.variant === 'chat' ? 1.6 : undefined,\n rehypePlugins,\n remarkPlugins,\n remarkPluginsAhead,\n components = {},\n customRender,\n showFootnotes = true,\n streamSmoothingPreset,\n citations,\n ...rest\n } = props;\n\n const delayedAnimated = useDelayedAnimated(animated);\n\n const Render = useCallback(\n ({\n enableStream,\n children,\n reactMarkdownProps,\n }: Pick<MarkdownProps, 'children' | 'enableStream' | 'reactMarkdownProps'>) => {\n const DefaultRender = enableStream ? StreamdownRender : MarkdownRender;\n const defaultDOM = <DefaultRender {...reactMarkdownProps}>{children}</DefaultRender>;\n return customRender ? customRender(defaultDOM, { text: children }) : defaultDOM;\n },\n [customRender],\n );\n\n return (\n <PreviewGroup enable={enableImageGallery}>\n <Typography\n borderRadius={borderRadius}\n className={cx(variants({ enableLatex, variant }), className)}\n data-code-type=\"markdown\"\n fontSize={fontSize}\n headerMultiple={headerMultiple}\n lineHeight={lineHeight}\n marginMultiple={marginMultiple}\n ref={ref}\n style={style}\n onDoubleClick={onDoubleClick}\n {...rest}\n >\n <MarkdownProvider\n allowHtml={allowHtml}\n animated={delayedAnimated}\n citations={citations}\n componentProps={componentProps}\n components={components}\n enableCustomFootnotes={enableCustomFootnotes}\n enableGithubAlert={enableGithubAlert}\n enableLatex={enableLatex}\n enableMermaid={enableMermaid}\n fullFeaturedCodeBlock={fullFeaturedCodeBlock}\n rehypePlugins={rehypePlugins}\n rehypePluginsAhead={rehypePluginsAhead}\n remarkPlugins={remarkPlugins}\n remarkPluginsAhead={remarkPluginsAhead}\n showFootnotes={showFootnotes}\n streamSmoothingPreset={streamSmoothingPreset}\n variant={variant}\n >\n <Render\n enableStream={enableStream && delayedAnimated}\n reactMarkdownProps={reactMarkdownProps}\n >\n {children}\n </Render>\n </MarkdownProvider>\n </Typography>\n </PreviewGroup>\n );\n});\n\nMarkdown.displayName = 'Markdown';\n\nexport default Markdown;\n"],"mappings":";;;;;;;;;;;;;;AAcA,MAAM,WAAW,MAAqB,UAAU;CAC9C,MAAM,EACJ,KACA,WAAW,IACX,WACA,OACA,uBACA,eACA,UACA,cAAc,MACd,gBAAgB,MAChB,oBACA,uBACA,mBACA,eAAe,MACf,gBACA,oBACA,WACA,cACA,WAAW,MAAM,YAAY,SAAS,KAAK,QAC3C,iBAAiB,MAAM,YAAY,SAAS,MAAO,QACnD,iBAAiB,MAAM,YAAY,SAAS,IAAI,QAChD,UAAU,WACV,oBACA,aAAa,MAAM,YAAY,SAAS,MAAM,QAC9C,eACA,eACA,oBACA,aAAa,EAAE,EACf,cACA,gBAAgB,MAChB,uBACA,WACA,GAAG,SACD;CAEJ,MAAM,kBAAkB,mBAAmB,SAAS;CAEpD,MAAM,SAAS,aACZ,EACC,8BACA,sBACA,+CAC6E;EAE7E,MAAM,aAAa,oBADGA,iBAAeC,2BAAmBC;GACtB,GAAIC;aAAqBC;IAAyB;AACpF,SAAO,eAAe,aAAa,YAAY,EAAE,MAAMA,YAAU,CAAC,GAAG;IAEvE,CAAC,aAAa,CACf;AAED,QACE,oBAACC;EAAa,QAAQ;YACpB,oBAACC;GACe;GACd,WAAW,GAAG,SAAS;IAAE;IAAa;IAAS,CAAC,EAAE,UAAU;GAC5D,kBAAe;GACL;GACM;GACJ;GACI;GACX;GACE;GACQ;GACf,GAAI;aAEJ,oBAAC;IACY;IACX,UAAU;IACC;IACK;IACJ;IACW;IACJ;IACN;IACE;IACQ;IACR;IACK;IACL;IACK;IACL;IACQ;IACd;cAET,oBAAC;KACC,cAAc,gBAAgB;KACV;KAEnB;MACM;KACQ;IACR;GACA;EAEjB;AAEF,SAAS,cAAc;AAEvB,uBAAe"}