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

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,21 @@ const zhCN = {
120
101
  zoomOut: '缩小',
121
102
  zoomIn: '放大',
122
103
  download: '下载',
104
+ fullScreen: '全屏',
105
+ exitFullScreen: '退出全屏',
106
+ downloadImage: '下载图片',
107
+ downloadedImage: '已下载',
108
+ copyImage: '复制图片',
109
+ copiedImage: '已复制',
110
+ fitInView: '适应页面',
123
111
  },
124
112
  };
125
113
 
126
- const ConfigContext = React.createContext({
114
+ const ConfigContext = react.createContext({
127
115
  locale: zhCN,
128
116
  });
129
117
  const ConfigProvider = ({ locale, children, mermaidConfig }) => {
130
- const contextValue = React.useMemo(() => {
118
+ const contextValue = react.useMemo(() => {
131
119
  const contextValue = {
132
120
  locale: locale || zhCN,
133
121
  };
@@ -140,7 +128,7 @@ const ConfigProvider = ({ locale, children, mermaidConfig }) => {
140
128
  };
141
129
  // Hook 用于在组件中使用配置
142
130
  const useConfig = () => {
143
- const context = React.useContext(ConfigContext);
131
+ const context = react.useContext(ConfigContext);
144
132
  return context;
145
133
  };
146
134
  // Hook 用于获取当前语言包
@@ -149,60 +137,86 @@ const useLocale = () => {
149
137
  return locale;
150
138
  };
151
139
 
152
- const TIMEOUT = 3000;
140
+ const Button = ({ className = '', children, icon, onClick, style, disabled = false, ...restProps }) => {
141
+ const handleClick = (e) => {
142
+ if (disabled) {
143
+ e.preventDefault();
144
+ return;
145
+ }
146
+ onClick?.();
147
+ };
148
+ return (jsxRuntime.jsxs("div", { role: "button", className: classNames({
149
+ 'ds-button': true,
150
+ 'ds-button__disabled': disabled,
151
+ }, className), onClick: handleClick, style: style, "aria-disabled": disabled, ...restProps, children: [icon && jsxRuntime.jsx("div", { className: "ds-button__icon", children: icon }), children] }));
152
+ };
153
+
154
+ const SuccessButton = (props) => {
155
+ const { onClick, icon, executeText, children, ...rest } = props;
156
+ const [isLoading, setIsLoading] = react.useState(false);
157
+ const [isSuccess, setIsSuccess] = react.useState(false);
158
+ const isUnmounted = react.useRef(false);
159
+ const handleClick = async () => {
160
+ if (isLoading || isSuccess) {
161
+ return;
162
+ }
163
+ try {
164
+ // 如果onClick不是异步函数,则直接调用
165
+ const returnValue = onClick();
166
+ if (returnValue instanceof Promise) {
167
+ setIsLoading(true);
168
+ const result = await returnValue;
169
+ if (result) {
170
+ setIsSuccess(true);
171
+ setTimeout(() => {
172
+ if (!isUnmounted.current) {
173
+ setIsSuccess(false);
174
+ }
175
+ }, 1000);
176
+ }
177
+ }
178
+ }
179
+ catch (error) {
180
+ setIsSuccess(false);
181
+ }
182
+ finally {
183
+ setIsLoading(false);
184
+ }
185
+ };
186
+ react.useEffect(() => {
187
+ isUnmounted.current = false;
188
+ return () => {
189
+ isUnmounted.current = true;
190
+ };
191
+ }, []);
192
+ return (jsxRuntime.jsx(Button, { ...rest, onClick: handleClick, icon: isSuccess ? jsxRuntime.jsx(CheckMarkIcon, { size: 24 }) : icon, children: isSuccess ? executeText || children : children }));
193
+ };
194
+
153
195
  const CopyButton = ({ codeContent, style, className }) => {
154
196
  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
197
  const handleCopy = async () => {
161
- if (isCopying || !codeContent)
162
- return;
163
- setIsCopying(true);
164
198
  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);
199
+ await navigator.clipboard.writeText(codeContent || '');
200
+ return true;
173
201
  }
174
202
  catch (err) {
175
203
  // 降级方案:使用传统方法
176
204
  const textArea = document.createElement('textarea');
177
- textArea.value = codeContent;
178
- document.body.appendChild(textArea);
205
+ textArea.value = codeContent || '';
179
206
  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);
207
+ document.execCommand('copy');
208
+ return true;
195
209
  }
196
210
  };
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 }) }));
211
+ 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
212
  };
199
213
 
200
214
  const DownloadButton = ({ codeContent, language, style, className }) => {
201
215
  const { locale } = useConfig();
202
216
  // 下载文件
203
- const handleDownload = () => {
217
+ const handleDownload = async () => {
204
218
  if (!codeContent)
205
- return;
219
+ return false;
206
220
  const blob = new Blob([codeContent], { type: 'text/plain;charset=utf-8' });
207
221
  const url = URL.createObjectURL(blob);
208
222
  const link = document.createElement('a');
@@ -248,8 +262,9 @@ const DownloadButton = ({ codeContent, language, style, className }) => {
248
262
  link.click();
249
263
  document.body.removeChild(link);
250
264
  URL.revokeObjectURL(url);
265
+ return true;
251
266
  };
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 }) }));
267
+ 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
268
  };
254
269
 
255
270
  const CodeBlockActions = ({ codeContent, language }) => {
@@ -291,7 +306,7 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
291
306
  const currentPlugins = themeState.plugins;
292
307
  const mathSplitSymbol = currentMath?.splitSymbol ?? 'dollar';
293
308
  const finalReplaceMathBracket = currentMath?.replaceMathBracket ?? replaceMathBracket;
294
- const { remarkPlugins, rehypePlugins, hasKatexPlugin, components } = React.useMemo(() => {
309
+ const { remarkPlugins, rehypePlugins, hasKatexPlugin, components } = react.useMemo(() => {
295
310
  let hasKatexPlugin = false;
296
311
  const components = {};
297
312
  const remarkPlugins = [gfmPlugin];
@@ -327,7 +342,7 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
327
342
  components,
328
343
  };
329
344
  }, [currentPlugins]);
330
- const children = React.useMemo(() => {
345
+ const children = react.useMemo(() => {
331
346
  /** 如果存在数学公式插件,并且数学公式分隔符为括号,则替换成 $ 符号 */
332
347
  if (hasKatexPlugin && mathSplitSymbol === 'bracket') {
333
348
  return finalReplaceMathBracket(_children);
@@ -342,30 +357,30 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
342
357
  ...components,
343
358
  }, ...props, children: children }));
344
359
  };
345
- var HighReactMarkdown$1 = React.memo(HighReactMarkdown);
360
+ var HighReactMarkdown$1 = react.memo(HighReactMarkdown);
346
361
 
347
362
  const useTypingTask = (options) => {
348
363
  const { timerType = 'setTimeout', interval, charsRef, onEnd, onStart, onBeforeTypedChar, onTypedChar, processCharDisplay, wholeContentRef, disableTyping, triggerUpdate, resetWholeContent, } = options;
349
364
  /** 是否卸载 */
350
- const isUnmountRef = React.useRef(false);
365
+ const isUnmountRef = react.useRef(false);
351
366
  /** 是否正在打字 */
352
- const isTypingRef = React.useRef(false);
367
+ const isTypingRef = react.useRef(false);
353
368
  /** 动画帧ID */
354
- const animationFrameRef = React.useRef(null);
369
+ const animationFrameRef = react.useRef(null);
355
370
  /** 传统定时器(兼容模式) */
356
- const timerRef = React.useRef(null);
371
+ const timerRef = react.useRef(null);
357
372
  // 已经打过的字记录
358
- const typedCharsRef = React.useRef(undefined);
373
+ const typedCharsRef = react.useRef(undefined);
359
374
  // 是否主动调用 stop 方法
360
- const typedIsManualStopRef = React.useRef(false);
361
- const disableTypingRef = React.useRef(disableTyping);
375
+ const typedIsManualStopRef = react.useRef(false);
376
+ const disableTypingRef = react.useRef(disableTyping);
362
377
  disableTypingRef.current = disableTyping;
363
- const intervalRef = React.useRef(interval);
378
+ const intervalRef = react.useRef(interval);
364
379
  intervalRef.current = interval;
365
380
  const getChars = () => {
366
381
  return charsRef.current;
367
382
  };
368
- React.useEffect(() => {
383
+ react.useEffect(() => {
369
384
  isUnmountRef.current = false;
370
385
  return () => {
371
386
  isUnmountRef.current = true;
@@ -678,30 +693,30 @@ const useTypingTask = (options) => {
678
693
  };
679
694
  };
680
695
 
681
- const MarkdownContext = React.createContext({});
696
+ const MarkdownContext = react.createContext({});
682
697
  const MarkdownProvider = ({ value, children }) => {
683
- const contextValue = React.useMemo(() => value, [value]);
698
+ const contextValue = react.useMemo(() => value, [value]);
684
699
  return jsxRuntime.jsx(MarkdownContext.Provider, { value: contextValue, children: children });
685
700
  };
686
701
 
687
- const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTypedChar, onBeforeTypedChar, timerType = 'setTimeout', disableTyping = false, autoStartTyping = true }, ref) => {
702
+ const MarkdownCMDInner = react.forwardRef(({ interval = 30, onEnd, onStart, onTypedChar, onBeforeTypedChar, timerType = 'setTimeout', disableTyping = false, autoStartTyping = true }, ref) => {
688
703
  const { state: themeState } = useMarkdownThemeContext();
689
704
  // 从 context 中获取主题配置
690
705
  const currentTheme = themeState.theme;
691
706
  /** 是否自动开启打字动画, 后面发生变化将不会生效 */
692
- const autoStartTypingRef = React.useRef(autoStartTyping);
707
+ const autoStartTypingRef = react.useRef(autoStartTyping);
693
708
  /** 是否打过字 */
694
- const isStartedTypingRef = React.useRef(false);
709
+ const isStartedTypingRef = react.useRef(false);
695
710
  /** 当前需要打字的内容 */
696
- const charsRef = React.useRef([]);
711
+ const charsRef = react.useRef([]);
697
712
  /**
698
713
  * 打字是否已经完全结束
699
714
  * 如果打字已经完全结束,则不会再触发打字效果
700
715
  */
701
- const isWholeTypedEndRef = React.useRef(false);
702
- const charIndexRef = React.useRef(0);
716
+ const isWholeTypedEndRef = react.useRef(false);
717
+ const charIndexRef = react.useRef(0);
703
718
  /** 整个内容引用 */
704
- const wholeContentRef = React.useRef({
719
+ const wholeContentRef = react.useRef({
705
720
  thinking: {
706
721
  content: '',
707
722
  length: 0,
@@ -714,7 +729,7 @@ const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTy
714
729
  },
715
730
  allLength: 0,
716
731
  });
717
- const [, setUpdate] = React.useState(0);
732
+ const [, setUpdate] = react.useState(0);
718
733
  const triggerUpdate = () => {
719
734
  setUpdate((prev) => prev + 1);
720
735
  };
@@ -798,7 +813,7 @@ const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTy
798
813
  manual: false,
799
814
  });
800
815
  };
801
- React.useImperativeHandle(ref, () => ({
816
+ react.useImperativeHandle(ref, () => ({
802
817
  /**
803
818
  * 添加内容
804
819
  * @param content 内容 {string}
@@ -871,7 +886,7 @@ const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTy
871
886
  if (__DEV__) {
872
887
  MarkdownCMDInner.displayName = 'MarkdownCMD';
873
888
  }
874
- const MarkdownCMD = React.forwardRef((props, ref) => {
889
+ const MarkdownCMD = react.forwardRef((props, ref) => {
875
890
  const { children = '', answerType = 'answer', isInnerRender, ...reset } = props;
876
891
  if (__DEV__) {
877
892
  if (!['thinking', 'answer'].includes(answerType)) {
@@ -881,9 +896,9 @@ const MarkdownCMD = React.forwardRef((props, ref) => {
881
896
  throw new Error('Markdown组件的子元素必须是一个字符串');
882
897
  }
883
898
  }
884
- const contextValue = React.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
899
+ const contextValue = react.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
885
900
  // 分离主题相关的 props
886
- const themeProps = React.useMemo(() => ({
901
+ const themeProps = react.useMemo(() => ({
887
902
  theme: props.theme || DEFAULT_THEME,
888
903
  math: props.math,
889
904
  codeBlock: props.codeBlock,
@@ -898,9 +913,9 @@ const MarkdownCMD = React.forwardRef((props, ref) => {
898
913
  });
899
914
 
900
915
  const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...rest }) => {
901
- const cmdRef = React.useRef(null);
902
- const prefixRef = React.useRef('');
903
- const content = React.useMemo(() => {
916
+ const cmdRef = react.useRef(null);
917
+ const prefixRef = react.useRef('');
918
+ const content = react.useMemo(() => {
904
919
  if (typeof _children === 'string') {
905
920
  return _children;
906
921
  }
@@ -909,7 +924,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
909
924
  }
910
925
  return '';
911
926
  }, [_children]);
912
- React.useEffect(() => {
927
+ react.useEffect(() => {
913
928
  if (prefixRef.current !== content) {
914
929
  let newContent = '';
915
930
  if (prefixRef.current === '') {
@@ -928,7 +943,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
928
943
  prefixRef.current = content;
929
944
  }
930
945
  }, [answerType, content]);
931
- React.useImperativeHandle(markdownRef, () => ({
946
+ react.useImperativeHandle(markdownRef, () => ({
932
947
  stop: () => {
933
948
  cmdRef.current.stop();
934
949
  },
@@ -946,7 +961,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
946
961
  const { theme, math, plugins, codeBlock, ...baseProps } = rest;
947
962
  return jsxRuntime.jsx(MarkdownCMD, { ref: cmdRef, ...baseProps, isInnerRender: true });
948
963
  };
949
- const Markdown = React.forwardRef((props, ref) => {
964
+ const Markdown = react.forwardRef((props, ref) => {
950
965
  const { children = '', answerType = 'answer', ...reset } = props;
951
966
  if (__DEV__) {
952
967
  if (!['thinking', 'answer'].includes(answerType)) {
@@ -956,9 +971,9 @@ const Markdown = React.forwardRef((props, ref) => {
956
971
  throw new Error('Markdown组件的子元素必须是一个字符串');
957
972
  }
958
973
  }
959
- const contextValue = React.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
974
+ const contextValue = react.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
960
975
  // 分离主题相关的 props
961
- const themeProps = React.useMemo(() => ({
976
+ const themeProps = react.useMemo(() => ({
962
977
  theme: props.theme || DEFAULT_THEME,
963
978
  math: props.math,
964
979
  codeBlock: props.codeBlock,
@@ -967,169 +982,12 @@ const Markdown = React.forwardRef((props, ref) => {
967
982
  }), [props.theme, props.math, props.codeBlock, props.plugins, props.answerType]);
968
983
  return (jsxRuntime.jsx(MarkdownProvider, { value: contextValue, children: jsxRuntime.jsx(MarkdownThemeProvider, { value: themeProps, children: jsxRuntime.jsx(MarkdownInner, { ...props, answerType: answerType, markdownRef: ref }) }) }));
969
984
  });
970
- var Markdown$1 = React.memo(Markdown);
985
+ var Markdown$1 = react.memo(Markdown);
971
986
 
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 });
987
+ const IconButton = ({ icon, className = '', ...restProps }) => {
988
+ return jsxRuntime.jsx(Button, { icon: icon, className: `ds-icon-button ${className}`, ...restProps });
974
989
  };
975
990
 
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
991
  const Segmented = ({ Segmented: segments, value, onChange }) => {
1134
992
  const handleClick = (itemValue) => {
1135
993
  onChange?.(itemValue);
@@ -1140,17 +998,20 @@ const Segmented = ({ Segmented: segments, value, onChange }) => {
1140
998
  /* eslint-disable react-refresh/only-export-components */
1141
999
 
1142
1000
  exports.Button = Button;
1001
+ exports.CheckMarkIcon = CheckMarkIcon;
1143
1002
  exports.CodeBlockActions = CodeBlockActions;
1144
1003
  exports.CodeBlockWrap = CodeBlockWrap;
1145
1004
  exports.ConfigProvider = ConfigProvider;
1146
1005
  exports.CopyButton = CopyButton;
1006
+ exports.CopyIcon = CopyIcon;
1147
1007
  exports.DownloadButton = DownloadButton;
1008
+ exports.DownloadIcon = DownloadIcon;
1148
1009
  exports.HighlightCode = HighlightCode;
1149
1010
  exports.IconButton = IconButton;
1150
1011
  exports.Markdown = Markdown$1;
1151
1012
  exports.MarkdownCMD = MarkdownCMD;
1152
1013
  exports.Segmented = Segmented;
1153
- exports.ToolTip = ToolTip;
1014
+ exports.SuccessButton = SuccessButton;
1154
1015
  exports.default = Markdown$1;
1155
1016
  exports.useConfig = useConfig;
1156
1017
  exports.useLocale = useLocale;