ds-markdown 0.1.10-beta.1 → 0.1.10-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -3,12 +3,11 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
- var React = require('react');
6
+ var react = require('react');
7
7
  var Markdown$2 = require('react-markdown');
8
8
  var gfmPlugin = require('remark-gfm');
9
9
  var classNames = require('classnames');
10
10
  var reactSyntaxHighlighter = require('react-syntax-highlighter');
11
- var reactDom = require('react-dom');
12
11
 
13
12
  /**
14
13
  * 将括号格式的数学公式转换为美元符号格式
@@ -24,44 +23,32 @@ var reactDom = require('react-dom');
24
23
  * @returns 转换后的字符串
25
24
  */
26
25
  const replaceMathBracket = (value) => {
27
- // 1. 提取并保护所有 Markdown 链接(包括图片和普通链接)
28
- // 匹配 ![alt](url) 或 [text](url) 形式
29
- const mdLinkMatches = [];
30
- const protectedValue = value.replace(/!?\[[^\]]*\]\([^)]*\)/g, (m) => {
31
- mdLinkMatches.push(m);
32
- return `__MD_LINK_${mdLinkMatches.length - 1}__`;
33
- });
34
- // 2. 提取所有块级公式内容,临时替换为占位符
35
- // 处理 \[...\] 格式的块级公式
26
+ // 1. 提取所有块级公式内容,临时替换为占位符, [...]
36
27
  const blockMatches = [];
37
- let replaced = protectedValue.replace(/\\*\[([\s\S]+?)\\*\]/g, (_m, p1) => {
28
+ let replaced = value.replace(/\\+\[([\s\S]+?)\\+\]/g, (_m, p1) => {
38
29
  blockMatches.push(p1);
39
30
  return `__BLOCK_MATH_${blockMatches.length - 1}__`;
40
31
  });
41
- // 处理 $$...$$ 格式的块级公式(兼容性处理)
32
+ // 也需要兼容 $$ xxxx $$ 这种写法
42
33
  replaced = replaced.replace(/\$\$([\s\S]+?)\$\$/g, (_m, p1) => {
43
34
  blockMatches.push(p1);
44
35
  return `__BLOCK_MATH_${blockMatches.length - 1}__`;
45
36
  });
46
- // 3. 替换块级公式外部的 \(...\) 为 $...$(行内公式)
47
- replaced = replaced.replace(/\\*\(([^)]+?)\\*\)/g, (_m, p1) => {
37
+ // 2. 替换块级公式外部的 ( ... ) 为 $...$
38
+ replaced = replaced.replace(/\\+\(([^)]+?)\\+\)/g, (_m, p1) => {
48
39
  return '$' + p1 + '$';
49
40
  });
50
- // 4. 还原块级公式内容,保持其内部小括号原样
41
+ // 3. 还原块级公式内容,保持其内部小括号原样
51
42
  replaced = replaced.replace(/__BLOCK_MATH_(\d+)__/g, (_m, idx) => {
52
43
  return '$$' + blockMatches[Number(idx)] + '$$';
53
44
  });
54
- // 5. 还原被保护的 Markdown 链接
55
- replaced = replaced.replace(/__MD_LINK_(\d+)__/g, (_m, idx) => {
56
- return mdLinkMatches[Number(idx)];
57
- });
58
45
  return replaced;
59
46
  };
60
47
 
61
48
  const DEFAULT_THEME = 'light';
62
49
  const DEFAULT_ANSWER_TYPE = 'answer';
63
50
  const DEFAULT_PLUGINS = [];
64
- const MarkdownThemeContext = React.createContext({
51
+ const MarkdownThemeContext = react.createContext({
65
52
  state: {
66
53
  theme: DEFAULT_THEME,
67
54
  answerType: DEFAULT_ANSWER_TYPE,
@@ -69,7 +56,7 @@ const MarkdownThemeContext = React.createContext({
69
56
  methods: {},
70
57
  });
71
58
  const MarkdownThemeProvider = ({ value = {}, children }) => {
72
- const contextValue = React.useMemo(() => ({
59
+ const contextValue = react.useMemo(() => ({
73
60
  state: {
74
61
  theme: DEFAULT_THEME,
75
62
  answerType: DEFAULT_ANSWER_TYPE,
@@ -81,9 +68,9 @@ const MarkdownThemeProvider = ({ value = {}, children }) => {
81
68
  }), [value]);
82
69
  return jsxRuntime.jsx(MarkdownThemeContext.Provider, { value: contextValue, children: children });
83
70
  };
84
- const useMarkdownThemeContext = () => React.useContext(MarkdownThemeContext);
71
+ const useMarkdownThemeContext = () => react.useContext(MarkdownThemeContext);
85
72
  const useThemeState = () => {
86
- return React.useContext(MarkdownThemeContext).state;
73
+ return react.useContext(MarkdownThemeContext).state;
87
74
  };
88
75
 
89
76
  const CodeBlockWrap = ({ children, title }) => {
@@ -91,13 +78,6 @@ const CodeBlockWrap = ({ children, title }) => {
91
78
  return (jsxRuntime.jsxs("div", { className: `md-code-block md-code-block-${theme}`, children: [jsxRuntime.jsx("div", { className: "md-code-block-banner-wrap", children: jsxRuntime.jsx("div", { className: "md-code-block-banner md-code-block-banner-lite", children: title }) }), jsxRuntime.jsx("div", { className: "md-code-block-content", children: children })] }));
92
79
  };
93
80
 
94
- const Button = ({ className = '', children, icon, onClick, style, ...restProps }) => {
95
- return (jsxRuntime.jsxs("div", { role: "button", className: classNames({
96
- 'ds-button': true,
97
- [className]: !!className,
98
- }), onClick: onClick, style: style, ...restProps, children: [icon && jsxRuntime.jsx("div", { className: "ds-button__icon", children: icon }), children] }));
99
- };
100
-
101
81
  const CheckMarkIcon = ({ size }) => {
102
82
  return (jsxRuntime.jsx("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M9.338 21.575a1.058 1.058 0 0 1-.53-.363L2.275 13.17a1.063 1.063 0 0 1 1.65-1.341l5.63 6.928L19.33 3.86a1.064 1.064 0 0 1 1.778 1.167L10.551 21.115a1.065 1.065 0 0 1-1.213.46z", fill: "currentColor" }) }));
103
83
  };
@@ -113,6 +93,7 @@ const zhCN = {
113
93
  copy: '复制',
114
94
  copied: '已复制',
115
95
  download: '下载',
96
+ downloaded: '已下载',
116
97
  },
117
98
  mermaid: {
118
99
  diagram: '图表',
@@ -120,14 +101,20 @@ const zhCN = {
120
101
  zoomOut: '缩小',
121
102
  zoomIn: '放大',
122
103
  download: '下载',
104
+ fullScreen: '全屏',
105
+ exitFullScreen: '退出全屏',
106
+ downloadImage: '下载图片',
107
+ downloadedImage: '已下载',
108
+ copyImage: '复制图片',
109
+ copiedImage: '已复制',
123
110
  },
124
111
  };
125
112
 
126
- const ConfigContext = React.createContext({
113
+ const ConfigContext = react.createContext({
127
114
  locale: zhCN,
128
115
  });
129
116
  const ConfigProvider = ({ locale, children, mermaidConfig }) => {
130
- const contextValue = React.useMemo(() => {
117
+ const contextValue = react.useMemo(() => {
131
118
  const contextValue = {
132
119
  locale: locale || zhCN,
133
120
  };
@@ -140,7 +127,7 @@ const ConfigProvider = ({ locale, children, mermaidConfig }) => {
140
127
  };
141
128
  // Hook 用于在组件中使用配置
142
129
  const useConfig = () => {
143
- const context = React.useContext(ConfigContext);
130
+ const context = react.useContext(ConfigContext);
144
131
  return context;
145
132
  };
146
133
  // Hook 用于获取当前语言包
@@ -149,60 +136,86 @@ const useLocale = () => {
149
136
  return locale;
150
137
  };
151
138
 
152
- const TIMEOUT = 3000;
139
+ const Button = ({ className = '', children, icon, onClick, style, disabled = false, ...restProps }) => {
140
+ const handleClick = (e) => {
141
+ if (disabled) {
142
+ e.preventDefault();
143
+ return;
144
+ }
145
+ onClick?.();
146
+ };
147
+ return (jsxRuntime.jsxs("div", { role: "button", className: classNames({
148
+ 'ds-button': true,
149
+ 'ds-button__disabled': disabled,
150
+ }, className), onClick: handleClick, style: style, "aria-disabled": disabled, ...restProps, children: [icon && jsxRuntime.jsx("div", { className: "ds-button__icon", children: icon }), children] }));
151
+ };
152
+
153
+ const SuccessButton = (props) => {
154
+ const { onClick, icon, executeText, children, ...rest } = props;
155
+ const [isLoading, setIsLoading] = react.useState(false);
156
+ const [isSuccess, setIsSuccess] = react.useState(false);
157
+ const isUnmounted = react.useRef(false);
158
+ const handleClick = async () => {
159
+ if (isLoading || isSuccess) {
160
+ return;
161
+ }
162
+ try {
163
+ // 如果onClick不是异步函数,则直接调用
164
+ const returnValue = onClick();
165
+ if (returnValue instanceof Promise) {
166
+ setIsLoading(true);
167
+ const result = await returnValue;
168
+ if (result) {
169
+ setIsSuccess(true);
170
+ setTimeout(() => {
171
+ if (!isUnmounted.current) {
172
+ setIsSuccess(false);
173
+ }
174
+ }, 1000);
175
+ }
176
+ }
177
+ }
178
+ catch (error) {
179
+ setIsSuccess(false);
180
+ }
181
+ finally {
182
+ setIsLoading(false);
183
+ }
184
+ };
185
+ react.useEffect(() => {
186
+ isUnmounted.current = false;
187
+ return () => {
188
+ isUnmounted.current = true;
189
+ };
190
+ }, []);
191
+ return (jsxRuntime.jsx(Button, { ...rest, onClick: handleClick, icon: isSuccess ? jsxRuntime.jsx(CheckMarkIcon, { size: 24 }) : icon, children: isSuccess ? executeText || children : children }));
192
+ };
193
+
153
194
  const CopyButton = ({ codeContent, style, className }) => {
154
195
  const { locale } = useConfig();
155
- const [copyText, setCopyText] = React.useState(locale.codeBlock.copy);
156
- const [showCheckmark, setShowCheckmark] = React.useState(false);
157
- const [isCopying, setIsCopying] = React.useState(false);
158
- // 下载文件
159
- // 复制到剪贴板
160
196
  const handleCopy = async () => {
161
- if (isCopying || !codeContent)
162
- return;
163
- setIsCopying(true);
164
197
  try {
165
- await navigator.clipboard.writeText(codeContent);
166
- setCopyText(locale.codeBlock.copied);
167
- setShowCheckmark(true);
168
- setTimeout(() => {
169
- setCopyText(locale.codeBlock.copy);
170
- setShowCheckmark(false);
171
- setIsCopying(false);
172
- }, TIMEOUT);
198
+ await navigator.clipboard.writeText(codeContent || '');
199
+ return true;
173
200
  }
174
201
  catch (err) {
175
202
  // 降级方案:使用传统方法
176
203
  const textArea = document.createElement('textarea');
177
- textArea.value = codeContent;
178
- document.body.appendChild(textArea);
204
+ textArea.value = codeContent || '';
179
205
  textArea.select();
180
- try {
181
- document.execCommand('copy');
182
- setCopyText(locale.codeBlock.copied);
183
- setShowCheckmark(true);
184
- setTimeout(() => {
185
- setCopyText(locale.codeBlock.copy);
186
- setShowCheckmark(false);
187
- setIsCopying(false);
188
- }, TIMEOUT);
189
- }
190
- catch (fallbackErr) {
191
- console.error('Fallback copy failed:', fallbackErr);
192
- setIsCopying(false);
193
- }
194
- document.body.removeChild(textArea);
206
+ document.execCommand('copy');
207
+ return true;
195
208
  }
196
209
  };
197
- return (jsxRuntime.jsx(Button, { style: style, className: className, icon: showCheckmark ? jsxRuntime.jsx(CheckMarkIcon, { size: 24 }) : jsxRuntime.jsx(CopyIcon, { size: 24 }), onClick: handleCopy, children: jsxRuntime.jsx("span", { children: copyText }) }));
210
+ return (jsxRuntime.jsx(SuccessButton, { onClick: handleCopy, icon: jsxRuntime.jsx(CopyIcon, { size: 24 }), executeText: locale.codeBlock.copied || 'copied', style: style, className: className, children: locale.codeBlock.copy || 'copy' }));
198
211
  };
199
212
 
200
213
  const DownloadButton = ({ codeContent, language, style, className }) => {
201
214
  const { locale } = useConfig();
202
215
  // 下载文件
203
- const handleDownload = () => {
216
+ const handleDownload = async () => {
204
217
  if (!codeContent)
205
- return;
218
+ return false;
206
219
  const blob = new Blob([codeContent], { type: 'text/plain;charset=utf-8' });
207
220
  const url = URL.createObjectURL(blob);
208
221
  const link = document.createElement('a');
@@ -248,8 +261,9 @@ const DownloadButton = ({ codeContent, language, style, className }) => {
248
261
  link.click();
249
262
  document.body.removeChild(link);
250
263
  URL.revokeObjectURL(url);
264
+ return true;
251
265
  };
252
- return (jsxRuntime.jsx(Button, { style: style, className: className, icon: jsxRuntime.jsx(DownloadIcon, { size: 24 }), onClick: handleDownload, children: jsxRuntime.jsx("span", { children: locale.codeBlock.download }) }));
266
+ return (jsxRuntime.jsx(SuccessButton, { onClick: handleDownload, icon: jsxRuntime.jsx(DownloadIcon, { size: 24 }), executeText: locale.codeBlock.downloaded || 'Downloaded', style: style, className: className, children: locale.codeBlock.download || 'Download' }));
253
267
  };
254
268
 
255
269
  const CodeBlockActions = ({ codeContent, language }) => {
@@ -291,7 +305,7 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
291
305
  const currentPlugins = themeState.plugins;
292
306
  const mathSplitSymbol = currentMath?.splitSymbol ?? 'dollar';
293
307
  const finalReplaceMathBracket = currentMath?.replaceMathBracket ?? replaceMathBracket;
294
- const { remarkPlugins, rehypePlugins, hasKatexPlugin, components } = React.useMemo(() => {
308
+ const { remarkPlugins, rehypePlugins, hasKatexPlugin, components } = react.useMemo(() => {
295
309
  let hasKatexPlugin = false;
296
310
  const components = {};
297
311
  const remarkPlugins = [gfmPlugin];
@@ -327,7 +341,7 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
327
341
  components,
328
342
  };
329
343
  }, [currentPlugins]);
330
- const children = React.useMemo(() => {
344
+ const children = react.useMemo(() => {
331
345
  /** 如果存在数学公式插件,并且数学公式分隔符为括号,则替换成 $ 符号 */
332
346
  if (hasKatexPlugin && mathSplitSymbol === 'bracket') {
333
347
  return finalReplaceMathBracket(_children);
@@ -342,30 +356,30 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
342
356
  ...components,
343
357
  }, ...props, children: children }));
344
358
  };
345
- var HighReactMarkdown$1 = React.memo(HighReactMarkdown);
359
+ var HighReactMarkdown$1 = react.memo(HighReactMarkdown);
346
360
 
347
361
  const useTypingTask = (options) => {
348
362
  const { timerType = 'setTimeout', interval, charsRef, onEnd, onStart, onBeforeTypedChar, onTypedChar, processCharDisplay, wholeContentRef, disableTyping, triggerUpdate, resetWholeContent, } = options;
349
363
  /** 是否卸载 */
350
- const isUnmountRef = React.useRef(false);
364
+ const isUnmountRef = react.useRef(false);
351
365
  /** 是否正在打字 */
352
- const isTypingRef = React.useRef(false);
366
+ const isTypingRef = react.useRef(false);
353
367
  /** 动画帧ID */
354
- const animationFrameRef = React.useRef(null);
368
+ const animationFrameRef = react.useRef(null);
355
369
  /** 传统定时器(兼容模式) */
356
- const timerRef = React.useRef(null);
370
+ const timerRef = react.useRef(null);
357
371
  // 已经打过的字记录
358
- const typedCharsRef = React.useRef(undefined);
372
+ const typedCharsRef = react.useRef(undefined);
359
373
  // 是否主动调用 stop 方法
360
- const typedIsManualStopRef = React.useRef(false);
361
- const disableTypingRef = React.useRef(disableTyping);
374
+ const typedIsManualStopRef = react.useRef(false);
375
+ const disableTypingRef = react.useRef(disableTyping);
362
376
  disableTypingRef.current = disableTyping;
363
- const intervalRef = React.useRef(interval);
377
+ const intervalRef = react.useRef(interval);
364
378
  intervalRef.current = interval;
365
379
  const getChars = () => {
366
380
  return charsRef.current;
367
381
  };
368
- React.useEffect(() => {
382
+ react.useEffect(() => {
369
383
  isUnmountRef.current = false;
370
384
  return () => {
371
385
  isUnmountRef.current = true;
@@ -678,30 +692,30 @@ const useTypingTask = (options) => {
678
692
  };
679
693
  };
680
694
 
681
- const MarkdownContext = React.createContext({});
695
+ const MarkdownContext = react.createContext({});
682
696
  const MarkdownProvider = ({ value, children }) => {
683
- const contextValue = React.useMemo(() => value, [value]);
697
+ const contextValue = react.useMemo(() => value, [value]);
684
698
  return jsxRuntime.jsx(MarkdownContext.Provider, { value: contextValue, children: children });
685
699
  };
686
700
 
687
- const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTypedChar, onBeforeTypedChar, timerType = 'setTimeout', disableTyping = false, autoStartTyping = true }, ref) => {
701
+ const MarkdownCMDInner = react.forwardRef(({ interval = 30, onEnd, onStart, onTypedChar, onBeforeTypedChar, timerType = 'setTimeout', disableTyping = false, autoStartTyping = true }, ref) => {
688
702
  const { state: themeState } = useMarkdownThemeContext();
689
703
  // 从 context 中获取主题配置
690
704
  const currentTheme = themeState.theme;
691
705
  /** 是否自动开启打字动画, 后面发生变化将不会生效 */
692
- const autoStartTypingRef = React.useRef(autoStartTyping);
706
+ const autoStartTypingRef = react.useRef(autoStartTyping);
693
707
  /** 是否打过字 */
694
- const isStartedTypingRef = React.useRef(false);
708
+ const isStartedTypingRef = react.useRef(false);
695
709
  /** 当前需要打字的内容 */
696
- const charsRef = React.useRef([]);
710
+ const charsRef = react.useRef([]);
697
711
  /**
698
712
  * 打字是否已经完全结束
699
713
  * 如果打字已经完全结束,则不会再触发打字效果
700
714
  */
701
- const isWholeTypedEndRef = React.useRef(false);
702
- const charIndexRef = React.useRef(0);
715
+ const isWholeTypedEndRef = react.useRef(false);
716
+ const charIndexRef = react.useRef(0);
703
717
  /** 整个内容引用 */
704
- const wholeContentRef = React.useRef({
718
+ const wholeContentRef = react.useRef({
705
719
  thinking: {
706
720
  content: '',
707
721
  length: 0,
@@ -714,7 +728,7 @@ const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTy
714
728
  },
715
729
  allLength: 0,
716
730
  });
717
- const [, setUpdate] = React.useState(0);
731
+ const [, setUpdate] = react.useState(0);
718
732
  const triggerUpdate = () => {
719
733
  setUpdate((prev) => prev + 1);
720
734
  };
@@ -798,7 +812,7 @@ const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTy
798
812
  manual: false,
799
813
  });
800
814
  };
801
- React.useImperativeHandle(ref, () => ({
815
+ react.useImperativeHandle(ref, () => ({
802
816
  /**
803
817
  * 添加内容
804
818
  * @param content 内容 {string}
@@ -871,7 +885,7 @@ const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTy
871
885
  if (__DEV__) {
872
886
  MarkdownCMDInner.displayName = 'MarkdownCMD';
873
887
  }
874
- const MarkdownCMD = React.forwardRef((props, ref) => {
888
+ const MarkdownCMD = react.forwardRef((props, ref) => {
875
889
  const { children = '', answerType = 'answer', isInnerRender, ...reset } = props;
876
890
  if (__DEV__) {
877
891
  if (!['thinking', 'answer'].includes(answerType)) {
@@ -881,9 +895,9 @@ const MarkdownCMD = React.forwardRef((props, ref) => {
881
895
  throw new Error('Markdown组件的子元素必须是一个字符串');
882
896
  }
883
897
  }
884
- const contextValue = React.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
898
+ const contextValue = react.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
885
899
  // 分离主题相关的 props
886
- const themeProps = React.useMemo(() => ({
900
+ const themeProps = react.useMemo(() => ({
887
901
  theme: props.theme || DEFAULT_THEME,
888
902
  math: props.math,
889
903
  codeBlock: props.codeBlock,
@@ -898,9 +912,9 @@ const MarkdownCMD = React.forwardRef((props, ref) => {
898
912
  });
899
913
 
900
914
  const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...rest }) => {
901
- const cmdRef = React.useRef(null);
902
- const prefixRef = React.useRef('');
903
- const content = React.useMemo(() => {
915
+ const cmdRef = react.useRef(null);
916
+ const prefixRef = react.useRef('');
917
+ const content = react.useMemo(() => {
904
918
  if (typeof _children === 'string') {
905
919
  return _children;
906
920
  }
@@ -909,7 +923,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
909
923
  }
910
924
  return '';
911
925
  }, [_children]);
912
- React.useEffect(() => {
926
+ react.useEffect(() => {
913
927
  if (prefixRef.current !== content) {
914
928
  let newContent = '';
915
929
  if (prefixRef.current === '') {
@@ -928,7 +942,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
928
942
  prefixRef.current = content;
929
943
  }
930
944
  }, [answerType, content]);
931
- React.useImperativeHandle(markdownRef, () => ({
945
+ react.useImperativeHandle(markdownRef, () => ({
932
946
  stop: () => {
933
947
  cmdRef.current.stop();
934
948
  },
@@ -946,7 +960,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
946
960
  const { theme, math, plugins, codeBlock, ...baseProps } = rest;
947
961
  return jsxRuntime.jsx(MarkdownCMD, { ref: cmdRef, ...baseProps, isInnerRender: true });
948
962
  };
949
- const Markdown = React.forwardRef((props, ref) => {
963
+ const Markdown = react.forwardRef((props, ref) => {
950
964
  const { children = '', answerType = 'answer', ...reset } = props;
951
965
  if (__DEV__) {
952
966
  if (!['thinking', 'answer'].includes(answerType)) {
@@ -956,9 +970,9 @@ const Markdown = React.forwardRef((props, ref) => {
956
970
  throw new Error('Markdown组件的子元素必须是一个字符串');
957
971
  }
958
972
  }
959
- const contextValue = React.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
973
+ const contextValue = react.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
960
974
  // 分离主题相关的 props
961
- const themeProps = React.useMemo(() => ({
975
+ const themeProps = react.useMemo(() => ({
962
976
  theme: props.theme || DEFAULT_THEME,
963
977
  math: props.math,
964
978
  codeBlock: props.codeBlock,
@@ -967,169 +981,12 @@ const Markdown = React.forwardRef((props, ref) => {
967
981
  }), [props.theme, props.math, props.codeBlock, props.plugins, props.answerType]);
968
982
  return (jsxRuntime.jsx(MarkdownProvider, { value: contextValue, children: jsxRuntime.jsx(MarkdownThemeProvider, { value: themeProps, children: jsxRuntime.jsx(MarkdownInner, { ...props, answerType: answerType, markdownRef: ref }) }) }));
969
983
  });
970
- var Markdown$1 = React.memo(Markdown);
984
+ var Markdown$1 = react.memo(Markdown);
971
985
 
972
- const IconButton = ({ icon, style, className = '', onClick, ...restProps }) => {
973
- return jsxRuntime.jsx(Button, { icon: icon, className: `ds-icon-button ${className}`, style: style, onClick: onClick, ...restProps });
986
+ const IconButton = ({ icon, className = '', ...restProps }) => {
987
+ return jsxRuntime.jsx(Button, { icon: icon, className: `ds-icon-button ${className}`, ...restProps });
974
988
  };
975
989
 
976
- const ToolTip = React.forwardRef(({ title, children, position = 'top', className = '', style, showArrow = true, delay = 200 }, ref) => {
977
- const [isVisible, setIsVisible] = React.useState(false);
978
- const [tooltipStyle, setTooltipStyle] = React.useState({});
979
- const triggerRef = React.useRef(null);
980
- const tooltipRef = React.useRef(null);
981
- const timeoutRef = React.useRef(undefined);
982
- // 转发ref到trigger元素
983
- React.useImperativeHandle(ref, () => triggerRef.current, []);
984
- const showTooltip = React.useCallback(() => {
985
- timeoutRef.current = window.setTimeout(() => {
986
- setIsVisible(true);
987
- }, delay);
988
- }, [delay]);
989
- const hideTooltip = React.useCallback(() => {
990
- if (timeoutRef.current) {
991
- clearTimeout(timeoutRef.current);
992
- }
993
- setIsVisible(false);
994
- }, []);
995
- const updatePosition = React.useCallback(() => {
996
- if (!triggerRef.current || !tooltipRef.current)
997
- return;
998
- const triggerRect = triggerRef.current.getBoundingClientRect();
999
- const tooltipRect = tooltipRef.current.getBoundingClientRect();
1000
- let top = 0;
1001
- let left = 0;
1002
- switch (position) {
1003
- case 'top':
1004
- top = triggerRect.top - tooltipRect.height - 8;
1005
- left = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
1006
- break;
1007
- case 'bottom':
1008
- top = triggerRect.bottom + 8;
1009
- left = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
1010
- break;
1011
- case 'left':
1012
- top = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
1013
- left = triggerRect.left - tooltipRect.width - 8;
1014
- break;
1015
- case 'right':
1016
- top = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
1017
- left = triggerRect.right + 8;
1018
- break;
1019
- }
1020
- setTooltipStyle({
1021
- position: 'fixed',
1022
- top: `${top}px`,
1023
- left: `${left}px`,
1024
- zIndex: 1000,
1025
- });
1026
- }, [position]);
1027
- React.useEffect(() => {
1028
- if (isVisible) {
1029
- updatePosition();
1030
- }
1031
- }, [isVisible, position, updatePosition]);
1032
- React.useEffect(() => {
1033
- const handleScroll = () => {
1034
- if (isVisible) {
1035
- updatePosition();
1036
- }
1037
- };
1038
- const handleResize = () => {
1039
- if (isVisible) {
1040
- updatePosition();
1041
- }
1042
- };
1043
- window.addEventListener('scroll', handleScroll, true);
1044
- window.addEventListener('resize', handleResize);
1045
- return () => {
1046
- window.removeEventListener('scroll', handleScroll, true);
1047
- window.removeEventListener('resize', handleResize);
1048
- };
1049
- }, [isVisible, updatePosition]);
1050
- React.useEffect(() => {
1051
- return () => {
1052
- if (timeoutRef.current) {
1053
- clearTimeout(timeoutRef.current);
1054
- }
1055
- };
1056
- }, []);
1057
- const renderTooltip = () => {
1058
- if (!isVisible)
1059
- return null;
1060
- const tooltipElement = (jsxRuntime.jsxs("div", { ref: tooltipRef, className: classNames('ds-tooltip', `ds-tooltip--${position}`), style: tooltipStyle, children: [jsxRuntime.jsx("div", { className: "ds-tooltip__title", children: title }), showArrow && jsxRuntime.jsx("div", { className: classNames('ds-tooltip__arrow', `ds-tooltip__arrow--${position}`) })] }));
1061
- return reactDom.createPortal(tooltipElement, document.body);
1062
- };
1063
- // 合并原有的事件处理器
1064
- const handleMouseEnter = React.useCallback((e) => {
1065
- e.stopPropagation(); // 阻止事件冒泡
1066
- showTooltip();
1067
- // 只在子元素有onMouseEnter时才调用
1068
- const props = children.props;
1069
- if (props.onMouseEnter) {
1070
- props.onMouseEnter(e);
1071
- }
1072
- }, [children.props, showTooltip]);
1073
- const handleMouseLeave = React.useCallback((e) => {
1074
- e.stopPropagation(); // 阻止事件冒泡
1075
- hideTooltip();
1076
- // 只在子元素有onMouseLeave时才调用
1077
- const props = children.props;
1078
- if (props.onMouseLeave) {
1079
- props.onMouseLeave(e);
1080
- }
1081
- }, [children.props, hideTooltip]);
1082
- const handleFocus = React.useCallback((e) => {
1083
- e.stopPropagation(); // 阻止事件冒泡
1084
- showTooltip();
1085
- // 只在子元素有onFocus时才调用
1086
- const props = children.props;
1087
- if (props.onFocus) {
1088
- props.onFocus(e);
1089
- }
1090
- }, [children.props, showTooltip]);
1091
- const handleBlur = React.useCallback((e) => {
1092
- e.stopPropagation(); // 阻止事件冒泡
1093
- hideTooltip();
1094
- // 只在子元素有onBlur时才调用
1095
- const props = children.props;
1096
- if (props.onBlur) {
1097
- props.onBlur(e);
1098
- }
1099
- }, [children.props, hideTooltip]);
1100
- // 处理onClick事件
1101
- const handleClick = React.useCallback((e) => {
1102
- // 调用原有的onClick
1103
- const props = children.props;
1104
- if (props.onClick) {
1105
- props.onClick(e);
1106
- }
1107
- }, [children.props]);
1108
- // 检查组件是否支持ref
1109
- const isForwardRef = React.isValidElement(children) &&
1110
- typeof children.type === 'function' &&
1111
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1112
- children.type.$$typeof === Symbol.for('react.forward_ref');
1113
- // 如果组件不支持ref,使用包装div的方式
1114
- if (!isForwardRef && typeof children.type === 'function') {
1115
- return (jsxRuntime.jsxs("div", { ref: triggerRef, className: classNames('ds-tooltip-trigger', className), style: style, onMouseEnter: showTooltip, onMouseLeave: hideTooltip, onFocus: showTooltip, onBlur: hideTooltip, children: [children, renderTooltip()] }));
1116
- }
1117
- // 使用 cloneElement 直接给子元素添加事件监听器和ref
1118
- const enhancedChild = React.cloneElement(children, {
1119
- ref: triggerRef,
1120
- className: classNames(children.props.className, className),
1121
- style: { ...children.props.style, ...style },
1122
- onMouseEnter: handleMouseEnter,
1123
- onMouseLeave: handleMouseLeave,
1124
- onFocus: handleFocus,
1125
- onBlur: handleBlur,
1126
- onClick: handleClick,
1127
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1128
- });
1129
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [enhancedChild, renderTooltip()] }));
1130
- });
1131
- ToolTip.displayName = 'ToolTip';
1132
-
1133
990
  const Segmented = ({ Segmented: segments, value, onChange }) => {
1134
991
  const handleClick = (itemValue) => {
1135
992
  onChange?.(itemValue);
@@ -1140,17 +997,20 @@ const Segmented = ({ Segmented: segments, value, onChange }) => {
1140
997
  /* eslint-disable react-refresh/only-export-components */
1141
998
 
1142
999
  exports.Button = Button;
1000
+ exports.CheckMarkIcon = CheckMarkIcon;
1143
1001
  exports.CodeBlockActions = CodeBlockActions;
1144
1002
  exports.CodeBlockWrap = CodeBlockWrap;
1145
1003
  exports.ConfigProvider = ConfigProvider;
1146
1004
  exports.CopyButton = CopyButton;
1005
+ exports.CopyIcon = CopyIcon;
1147
1006
  exports.DownloadButton = DownloadButton;
1007
+ exports.DownloadIcon = DownloadIcon;
1148
1008
  exports.HighlightCode = HighlightCode;
1149
1009
  exports.IconButton = IconButton;
1150
1010
  exports.Markdown = Markdown$1;
1151
1011
  exports.MarkdownCMD = MarkdownCMD;
1152
1012
  exports.Segmented = Segmented;
1153
- exports.ToolTip = ToolTip;
1013
+ exports.SuccessButton = SuccessButton;
1154
1014
  exports.default = Markdown$1;
1155
1015
  exports.useConfig = useConfig;
1156
1016
  exports.useLocale = useLocale;