ds-markdown 0.1.9-beta.3 → 0.1.9-beta.5
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/i18n/en/index.d.ts +7 -0
- package/dist/cjs/i18n/en/index.js +7 -0
- package/dist/cjs/i18n/en/index.js.map +1 -1
- package/dist/cjs/i18n/zh/index.d.ts +7 -0
- package/dist/cjs/i18n/zh/index.js +7 -0
- package/dist/cjs/i18n/zh/index.js.map +1 -1
- package/dist/cjs/index.d.ts +34 -1
- package/dist/cjs/index.js +227 -52
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/i18n/en/index.d.ts +7 -0
- package/dist/esm/i18n/en/index.js +7 -0
- package/dist/esm/i18n/en/index.js.map +1 -1
- package/dist/esm/i18n/zh/index.d.ts +7 -0
- package/dist/esm/i18n/zh/index.js +7 -0
- package/dist/esm/i18n/zh/index.js.map +1 -1
- package/dist/esm/index.d.ts +34 -1
- package/dist/esm/index.js +180 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/style.css +132 -0
- package/package.json +1 -1
|
@@ -4,6 +4,13 @@ declare const enUS: {
|
|
|
4
4
|
readonly copied: "Copied";
|
|
5
5
|
readonly download: "Download";
|
|
6
6
|
};
|
|
7
|
+
readonly mermaid: {
|
|
8
|
+
readonly diagram: "Diagram";
|
|
9
|
+
readonly code: "Code";
|
|
10
|
+
readonly zoomOut: "Zoom Out";
|
|
11
|
+
readonly zoomIn: "Zoom In";
|
|
12
|
+
readonly download: "Download";
|
|
13
|
+
};
|
|
7
14
|
};
|
|
8
15
|
type EnUS = typeof enUS;
|
|
9
16
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/i18n/en/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAa,MAAA,IAAI,GAAG;AAClB,IAAA,SAAS,EAAE;AACT,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,MAAM,EAAE,QAAQ;AAChB,QAAA,QAAQ,EAAE,UAAU;AACrB,KAAA;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/i18n/en/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAa,MAAA,IAAI,GAAG;AAClB,IAAA,SAAS,EAAE;AACT,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,MAAM,EAAE,QAAQ;AAChB,QAAA,QAAQ,EAAE,UAAU;AACrB,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,OAAO,EAAE,SAAS;AAClB,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,OAAO,EAAE,UAAU;AACnB,QAAA,MAAM,EAAE,SAAS;AACjB,QAAA,QAAQ,EAAE,UAAU;AACrB,KAAA;;;;;;"}
|
|
@@ -4,6 +4,13 @@ declare const zhCN: {
|
|
|
4
4
|
readonly copied: "已复制";
|
|
5
5
|
readonly download: "下载";
|
|
6
6
|
};
|
|
7
|
+
readonly mermaid: {
|
|
8
|
+
readonly diagram: "图表";
|
|
9
|
+
readonly code: "代码";
|
|
10
|
+
readonly zoomOut: "缩小";
|
|
11
|
+
readonly zoomIn: "放大";
|
|
12
|
+
readonly download: "下载";
|
|
13
|
+
};
|
|
7
14
|
};
|
|
8
15
|
type ZhCN = typeof zhCN;
|
|
9
16
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/i18n/zh/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAa,MAAA,IAAI,GAAG;AAClB,IAAA,SAAS,EAAE;AACT,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,MAAM,EAAE,KAAK;AACb,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/i18n/zh/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAa,MAAA,IAAI,GAAG;AAClB,IAAA,SAAS,EAAE;AACT,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,MAAM,EAAE,KAAK;AACb,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA;;;;;;"}
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -123,6 +123,26 @@ interface ButtonProps {
|
|
|
123
123
|
}
|
|
124
124
|
declare const Button: React__default.FC<ButtonProps>;
|
|
125
125
|
|
|
126
|
+
interface IconButtonProps {
|
|
127
|
+
icon: React__default.ReactNode;
|
|
128
|
+
style?: React__default.CSSProperties;
|
|
129
|
+
className?: string;
|
|
130
|
+
onClick?: () => void;
|
|
131
|
+
}
|
|
132
|
+
declare const IconButton: React__default.FC<IconButtonProps>;
|
|
133
|
+
|
|
134
|
+
type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
|
|
135
|
+
interface ToolTipProps {
|
|
136
|
+
title: React__default.ReactNode;
|
|
137
|
+
children: React__default.ReactElement;
|
|
138
|
+
position?: TooltipPosition;
|
|
139
|
+
className?: string;
|
|
140
|
+
style?: React__default.CSSProperties;
|
|
141
|
+
showArrow?: boolean;
|
|
142
|
+
delay?: number;
|
|
143
|
+
}
|
|
144
|
+
declare const ToolTip: React__default.ForwardRefExoticComponent<ToolTipProps & React__default.RefAttributes<HTMLElement>>;
|
|
145
|
+
|
|
126
146
|
interface CopyButtonProps {
|
|
127
147
|
codeContent?: string;
|
|
128
148
|
style?: React__default.CSSProperties;
|
|
@@ -150,6 +170,12 @@ interface CodeBlockWrapProps {
|
|
|
150
170
|
}
|
|
151
171
|
declare const CodeBlockWrap: React__default.FC<CodeBlockWrapProps>;
|
|
152
172
|
|
|
173
|
+
interface HighlightCodeProps {
|
|
174
|
+
code: string;
|
|
175
|
+
language: string;
|
|
176
|
+
}
|
|
177
|
+
declare const HighlightCode: React__default.FC<HighlightCodeProps>;
|
|
178
|
+
|
|
153
179
|
declare namespace Mermaid {
|
|
154
180
|
/**
|
|
155
181
|
* The font size to use
|
|
@@ -1671,6 +1697,13 @@ interface Locale {
|
|
|
1671
1697
|
download: string;
|
|
1672
1698
|
[key: string]: string;
|
|
1673
1699
|
};
|
|
1700
|
+
mermaid: {
|
|
1701
|
+
diagram: string;
|
|
1702
|
+
code: string;
|
|
1703
|
+
zoomOut: string;
|
|
1704
|
+
zoomIn: string;
|
|
1705
|
+
download: string;
|
|
1706
|
+
};
|
|
1674
1707
|
[key: string]: unknown;
|
|
1675
1708
|
}
|
|
1676
1709
|
interface ConfigProviderProps {
|
|
@@ -1688,5 +1721,5 @@ declare const useLocale: () => Locale;
|
|
|
1688
1721
|
|
|
1689
1722
|
declare const useThemeState: () => IMarkdownThemeStateProps;
|
|
1690
1723
|
|
|
1691
|
-
export { Button, CodeBlockActions, CodeBlockWrap, ConfigProvider, CopyButton, DownloadButton, _default as Markdown, MarkdownCMD, _default as default, useConfig, useLocale, useThemeState };
|
|
1724
|
+
export { Button, CodeBlockActions, CodeBlockWrap, ConfigProvider, CopyButton, DownloadButton, HighlightCode, IconButton, _default as Markdown, MarkdownCMD, ToolTip, _default as default, useConfig, useLocale, useThemeState };
|
|
1692
1725
|
export type { ConfigContextType, ConfigProviderProps, IMarkdownMath, ITypedChar, Locale, MarkdownCMDProps, MarkdownCMDRef, MarkdownProps, MarkdownRef };
|
package/dist/cjs/index.js
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
var
|
|
6
|
+
var React = require('react');
|
|
7
7
|
var Markdown$2 = require('react-markdown');
|
|
8
|
-
var reactSyntaxHighlighter = require('react-syntax-highlighter');
|
|
9
8
|
var gfmPlugin = require('remark-gfm');
|
|
10
9
|
var classNames = require('classnames');
|
|
10
|
+
var reactSyntaxHighlighter = require('react-syntax-highlighter');
|
|
11
|
+
var reactDom = require('react-dom');
|
|
11
12
|
|
|
12
13
|
const replaceMathBracket = (value) => {
|
|
13
14
|
// 1. 提取所有块级公式内容,临时替换为占位符, [...]
|
|
@@ -35,7 +36,7 @@ const replaceMathBracket = (value) => {
|
|
|
35
36
|
const DEFAULT_THEME = 'light';
|
|
36
37
|
const DEFAULT_ANSWER_TYPE = 'answer';
|
|
37
38
|
const DEFAULT_PLUGINS = [];
|
|
38
|
-
const MarkdownThemeContext =
|
|
39
|
+
const MarkdownThemeContext = React.createContext({
|
|
39
40
|
state: {
|
|
40
41
|
theme: DEFAULT_THEME,
|
|
41
42
|
answerType: DEFAULT_ANSWER_TYPE,
|
|
@@ -43,7 +44,7 @@ const MarkdownThemeContext = react.createContext({
|
|
|
43
44
|
methods: {},
|
|
44
45
|
});
|
|
45
46
|
const MarkdownThemeProvider = ({ value = {}, children }) => {
|
|
46
|
-
const contextValue =
|
|
47
|
+
const contextValue = React.useMemo(() => ({
|
|
47
48
|
state: {
|
|
48
49
|
theme: DEFAULT_THEME,
|
|
49
50
|
answerType: DEFAULT_ANSWER_TYPE,
|
|
@@ -55,9 +56,9 @@ const MarkdownThemeProvider = ({ value = {}, children }) => {
|
|
|
55
56
|
}), [value]);
|
|
56
57
|
return jsxRuntime.jsx(MarkdownThemeContext.Provider, { value: contextValue, children: children });
|
|
57
58
|
};
|
|
58
|
-
const useMarkdownThemeContext = () =>
|
|
59
|
+
const useMarkdownThemeContext = () => React.useContext(MarkdownThemeContext);
|
|
59
60
|
const useThemeState = () => {
|
|
60
|
-
return
|
|
61
|
+
return React.useContext(MarkdownThemeContext).state;
|
|
61
62
|
};
|
|
62
63
|
|
|
63
64
|
const CodeBlockWrap = ({ children, title }) => {
|
|
@@ -65,11 +66,11 @@ const CodeBlockWrap = ({ children, title }) => {
|
|
|
65
66
|
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 })] }));
|
|
66
67
|
};
|
|
67
68
|
|
|
68
|
-
const Button = ({ className = '', children, icon, onClick, style }) => {
|
|
69
|
+
const Button = ({ className = '', children, icon, onClick, style, ...restProps }) => {
|
|
69
70
|
return (jsxRuntime.jsxs("div", { role: "button", className: classNames({
|
|
70
71
|
'ds-button': true,
|
|
71
72
|
[className]: !!className,
|
|
72
|
-
}), onClick: onClick, style: style, children: [icon && jsxRuntime.jsx("div", { className: "ds-button__icon", children: icon }), children] }));
|
|
73
|
+
}), onClick: onClick, style: style, ...restProps, children: [icon && jsxRuntime.jsx("div", { className: "ds-button__icon", children: icon }), children] }));
|
|
73
74
|
};
|
|
74
75
|
|
|
75
76
|
const CheckMarkIcon = ({ size }) => {
|
|
@@ -88,13 +89,20 @@ const zhCN = {
|
|
|
88
89
|
copied: '已复制',
|
|
89
90
|
download: '下载',
|
|
90
91
|
},
|
|
92
|
+
mermaid: {
|
|
93
|
+
diagram: '图表',
|
|
94
|
+
code: '代码',
|
|
95
|
+
zoomOut: '缩小',
|
|
96
|
+
zoomIn: '放大',
|
|
97
|
+
download: '下载',
|
|
98
|
+
},
|
|
91
99
|
};
|
|
92
100
|
|
|
93
|
-
const ConfigContext =
|
|
101
|
+
const ConfigContext = React.createContext({
|
|
94
102
|
locale: zhCN,
|
|
95
103
|
});
|
|
96
104
|
const ConfigProvider = ({ locale, children, mermaidConfig }) => {
|
|
97
|
-
const contextValue =
|
|
105
|
+
const contextValue = React.useMemo(() => {
|
|
98
106
|
const contextValue = {
|
|
99
107
|
locale: locale || zhCN,
|
|
100
108
|
};
|
|
@@ -107,7 +115,7 @@ const ConfigProvider = ({ locale, children, mermaidConfig }) => {
|
|
|
107
115
|
};
|
|
108
116
|
// Hook 用于在组件中使用配置
|
|
109
117
|
const useConfig = () => {
|
|
110
|
-
const context =
|
|
118
|
+
const context = React.useContext(ConfigContext);
|
|
111
119
|
return context;
|
|
112
120
|
};
|
|
113
121
|
// Hook 用于获取当前语言包
|
|
@@ -119,9 +127,9 @@ const useLocale = () => {
|
|
|
119
127
|
const TIMEOUT = 3000;
|
|
120
128
|
const CopyButton = ({ codeContent, style, className }) => {
|
|
121
129
|
const { locale } = useConfig();
|
|
122
|
-
const [copyText, setCopyText] =
|
|
123
|
-
const [showCheckmark, setShowCheckmark] =
|
|
124
|
-
const [isCopying, setIsCopying] =
|
|
130
|
+
const [copyText, setCopyText] = React.useState(locale.codeBlock.copy);
|
|
131
|
+
const [showCheckmark, setShowCheckmark] = React.useState(false);
|
|
132
|
+
const [isCopying, setIsCopying] = React.useState(false);
|
|
125
133
|
// 下载文件
|
|
126
134
|
// 复制到剪贴板
|
|
127
135
|
const handleCopy = async () => {
|
|
@@ -242,11 +250,14 @@ const ID_PREFIX__ = '__ds-markdown__';
|
|
|
242
250
|
/** 数学公式插件id */
|
|
243
251
|
const katexId = `${ID_PREFIX__}katex`;
|
|
244
252
|
|
|
245
|
-
const
|
|
253
|
+
const HighlightCode = ({ code, language }) => {
|
|
254
|
+
return (jsxRuntime.jsx(reactSyntaxHighlighter.Prism, { useInlineStyles: false, language: language, style: {}, children: code }));
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const CodeComponent = ({ className, children = '' }) => {
|
|
246
258
|
const match = /language-(\w+)/.exec(className || '');
|
|
247
259
|
const codeContent = String(children).replace(/\n$/, '');
|
|
248
|
-
|
|
249
|
-
return match ? (jsxRuntime.jsx(BlockWrap, { language: match[1], codeContent: codeContent, children: jsxRuntime.jsx(reactSyntaxHighlighter.Prism, { useInlineStyles: false, language: match[1], style: {}, children: codeContent }) })) : (jsxRuntime.jsx("code", { className: className, children: children }));
|
|
260
|
+
return match ? (jsxRuntime.jsx(BlockWrap, { language: match[1], codeContent: codeContent, children: jsxRuntime.jsx(HighlightCode, { code: codeContent, language: match[1] }) })) : (jsxRuntime.jsx("code", { className: className, children: children }));
|
|
250
261
|
};
|
|
251
262
|
const HighReactMarkdown = ({ children: _children, ...props }) => {
|
|
252
263
|
const { state: themeState } = useMarkdownThemeContext();
|
|
@@ -254,7 +265,7 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
|
|
|
254
265
|
const currentMath = themeState.math;
|
|
255
266
|
const currentPlugins = themeState.plugins;
|
|
256
267
|
const mathSplitSymbol = currentMath?.splitSymbol ?? 'dollar';
|
|
257
|
-
const { remarkPlugins, rehypePlugins, hasKatexPlugin, components } =
|
|
268
|
+
const { remarkPlugins, rehypePlugins, hasKatexPlugin, components } = React.useMemo(() => {
|
|
258
269
|
let hasKatexPlugin = false;
|
|
259
270
|
const components = {};
|
|
260
271
|
const remarkPlugins = [gfmPlugin];
|
|
@@ -290,7 +301,7 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
|
|
|
290
301
|
components,
|
|
291
302
|
};
|
|
292
303
|
}, [currentPlugins]);
|
|
293
|
-
const children =
|
|
304
|
+
const children = React.useMemo(() => {
|
|
294
305
|
/** 如果存在数学公式插件,并且数学公式分隔符为括号,则替换成 $ 符号 */
|
|
295
306
|
if (hasKatexPlugin && mathSplitSymbol === 'bracket') {
|
|
296
307
|
return replaceMathBracket(_children);
|
|
@@ -305,30 +316,30 @@ const HighReactMarkdown = ({ children: _children, ...props }) => {
|
|
|
305
316
|
...components,
|
|
306
317
|
}, ...props, children: children }));
|
|
307
318
|
};
|
|
308
|
-
var HighReactMarkdown$1 =
|
|
319
|
+
var HighReactMarkdown$1 = React.memo(HighReactMarkdown);
|
|
309
320
|
|
|
310
321
|
const useTypingTask = (options) => {
|
|
311
322
|
const { timerType = 'setTimeout', interval, charsRef, onEnd, onStart, onBeforeTypedChar, onTypedChar, processCharDisplay, wholeContentRef, disableTyping, triggerUpdate, resetWholeContent, } = options;
|
|
312
323
|
/** 是否卸载 */
|
|
313
|
-
const isUnmountRef =
|
|
324
|
+
const isUnmountRef = React.useRef(false);
|
|
314
325
|
/** 是否正在打字 */
|
|
315
|
-
const isTypingRef =
|
|
326
|
+
const isTypingRef = React.useRef(false);
|
|
316
327
|
/** 动画帧ID */
|
|
317
|
-
const animationFrameRef =
|
|
328
|
+
const animationFrameRef = React.useRef(null);
|
|
318
329
|
/** 传统定时器(兼容模式) */
|
|
319
|
-
const timerRef =
|
|
330
|
+
const timerRef = React.useRef(null);
|
|
320
331
|
// 已经打过的字记录
|
|
321
|
-
const typedCharsRef =
|
|
332
|
+
const typedCharsRef = React.useRef(undefined);
|
|
322
333
|
// 是否主动调用 stop 方法
|
|
323
|
-
const typedIsManualStopRef =
|
|
324
|
-
const disableTypingRef =
|
|
334
|
+
const typedIsManualStopRef = React.useRef(false);
|
|
335
|
+
const disableTypingRef = React.useRef(disableTyping);
|
|
325
336
|
disableTypingRef.current = disableTyping;
|
|
326
|
-
const intervalRef =
|
|
337
|
+
const intervalRef = React.useRef(interval);
|
|
327
338
|
intervalRef.current = interval;
|
|
328
339
|
const getChars = () => {
|
|
329
340
|
return charsRef.current;
|
|
330
341
|
};
|
|
331
|
-
|
|
342
|
+
React.useEffect(() => {
|
|
332
343
|
isUnmountRef.current = false;
|
|
333
344
|
return () => {
|
|
334
345
|
isUnmountRef.current = true;
|
|
@@ -641,30 +652,30 @@ const useTypingTask = (options) => {
|
|
|
641
652
|
};
|
|
642
653
|
};
|
|
643
654
|
|
|
644
|
-
const MarkdownContext =
|
|
655
|
+
const MarkdownContext = React.createContext({});
|
|
645
656
|
const MarkdownProvider = ({ value, children }) => {
|
|
646
|
-
const contextValue =
|
|
657
|
+
const contextValue = React.useMemo(() => value, [value]);
|
|
647
658
|
return jsxRuntime.jsx(MarkdownContext.Provider, { value: contextValue, children: children });
|
|
648
659
|
};
|
|
649
660
|
|
|
650
|
-
const MarkdownCMDInner =
|
|
661
|
+
const MarkdownCMDInner = React.forwardRef(({ interval = 30, onEnd, onStart, onTypedChar, onBeforeTypedChar, timerType = 'setTimeout', disableTyping = false, autoStartTyping = true }, ref) => {
|
|
651
662
|
const { state: themeState } = useMarkdownThemeContext();
|
|
652
663
|
// 从 context 中获取主题配置
|
|
653
664
|
const currentTheme = themeState.theme;
|
|
654
665
|
/** 是否自动开启打字动画, 后面发生变化将不会生效 */
|
|
655
|
-
const autoStartTypingRef =
|
|
666
|
+
const autoStartTypingRef = React.useRef(autoStartTyping);
|
|
656
667
|
/** 是否打过字 */
|
|
657
|
-
const isStartedTypingRef =
|
|
668
|
+
const isStartedTypingRef = React.useRef(false);
|
|
658
669
|
/** 当前需要打字的内容 */
|
|
659
|
-
const charsRef =
|
|
670
|
+
const charsRef = React.useRef([]);
|
|
660
671
|
/**
|
|
661
672
|
* 打字是否已经完全结束
|
|
662
673
|
* 如果打字已经完全结束,则不会再触发打字效果
|
|
663
674
|
*/
|
|
664
|
-
const isWholeTypedEndRef =
|
|
665
|
-
const charIndexRef =
|
|
675
|
+
const isWholeTypedEndRef = React.useRef(false);
|
|
676
|
+
const charIndexRef = React.useRef(0);
|
|
666
677
|
/** 整个内容引用 */
|
|
667
|
-
const wholeContentRef =
|
|
678
|
+
const wholeContentRef = React.useRef({
|
|
668
679
|
thinking: {
|
|
669
680
|
content: '',
|
|
670
681
|
length: 0,
|
|
@@ -677,7 +688,7 @@ const MarkdownCMDInner = react.forwardRef(({ interval = 30, onEnd, onStart, onTy
|
|
|
677
688
|
},
|
|
678
689
|
allLength: 0,
|
|
679
690
|
});
|
|
680
|
-
const [, setUpdate] =
|
|
691
|
+
const [, setUpdate] = React.useState(0);
|
|
681
692
|
const triggerUpdate = () => {
|
|
682
693
|
setUpdate((prev) => prev + 1);
|
|
683
694
|
};
|
|
@@ -761,7 +772,7 @@ const MarkdownCMDInner = react.forwardRef(({ interval = 30, onEnd, onStart, onTy
|
|
|
761
772
|
manual: false,
|
|
762
773
|
});
|
|
763
774
|
};
|
|
764
|
-
|
|
775
|
+
React.useImperativeHandle(ref, () => ({
|
|
765
776
|
/**
|
|
766
777
|
* 添加内容
|
|
767
778
|
* @param content 内容 {string}
|
|
@@ -834,7 +845,7 @@ const MarkdownCMDInner = react.forwardRef(({ interval = 30, onEnd, onStart, onTy
|
|
|
834
845
|
if (__DEV__) {
|
|
835
846
|
MarkdownCMDInner.displayName = 'MarkdownCMD';
|
|
836
847
|
}
|
|
837
|
-
const MarkdownCMD =
|
|
848
|
+
const MarkdownCMD = React.forwardRef((props, ref) => {
|
|
838
849
|
const { children = '', answerType = 'answer', isInnerRender, ...reset } = props;
|
|
839
850
|
if (__DEV__) {
|
|
840
851
|
if (!['thinking', 'answer'].includes(answerType)) {
|
|
@@ -844,9 +855,9 @@ const MarkdownCMD = react.forwardRef((props, ref) => {
|
|
|
844
855
|
throw new Error('Markdown组件的子元素必须是一个字符串');
|
|
845
856
|
}
|
|
846
857
|
}
|
|
847
|
-
const contextValue =
|
|
858
|
+
const contextValue = React.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
|
|
848
859
|
// 分离主题相关的 props
|
|
849
|
-
const themeProps =
|
|
860
|
+
const themeProps = React.useMemo(() => ({
|
|
850
861
|
theme: props.theme || DEFAULT_THEME,
|
|
851
862
|
math: props.math,
|
|
852
863
|
codeBlock: props.codeBlock,
|
|
@@ -861,9 +872,9 @@ const MarkdownCMD = react.forwardRef((props, ref) => {
|
|
|
861
872
|
});
|
|
862
873
|
|
|
863
874
|
const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...rest }) => {
|
|
864
|
-
const cmdRef =
|
|
865
|
-
const prefixRef =
|
|
866
|
-
const content =
|
|
875
|
+
const cmdRef = React.useRef(null);
|
|
876
|
+
const prefixRef = React.useRef('');
|
|
877
|
+
const content = React.useMemo(() => {
|
|
867
878
|
if (typeof _children === 'string') {
|
|
868
879
|
return _children;
|
|
869
880
|
}
|
|
@@ -872,7 +883,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
|
|
|
872
883
|
}
|
|
873
884
|
return '';
|
|
874
885
|
}, [_children]);
|
|
875
|
-
|
|
886
|
+
React.useEffect(() => {
|
|
876
887
|
if (prefixRef.current !== content) {
|
|
877
888
|
let newContent = '';
|
|
878
889
|
if (prefixRef.current === '') {
|
|
@@ -891,7 +902,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
|
|
|
891
902
|
prefixRef.current = content;
|
|
892
903
|
}
|
|
893
904
|
}, [answerType, content]);
|
|
894
|
-
|
|
905
|
+
React.useImperativeHandle(markdownRef, () => ({
|
|
895
906
|
stop: () => {
|
|
896
907
|
cmdRef.current.stop();
|
|
897
908
|
},
|
|
@@ -909,7 +920,7 @@ const MarkdownInner = ({ children: _children = '', answerType, markdownRef, ...r
|
|
|
909
920
|
const { theme, math, plugins, codeBlock, ...baseProps } = rest;
|
|
910
921
|
return jsxRuntime.jsx(MarkdownCMD, { ref: cmdRef, ...baseProps, isInnerRender: true });
|
|
911
922
|
};
|
|
912
|
-
const Markdown =
|
|
923
|
+
const Markdown = React.forwardRef((props, ref) => {
|
|
913
924
|
const { children = '', answerType = 'answer', ...reset } = props;
|
|
914
925
|
if (__DEV__) {
|
|
915
926
|
if (!['thinking', 'answer'].includes(answerType)) {
|
|
@@ -919,9 +930,9 @@ const Markdown = react.forwardRef((props, ref) => {
|
|
|
919
930
|
throw new Error('Markdown组件的子元素必须是一个字符串');
|
|
920
931
|
}
|
|
921
932
|
}
|
|
922
|
-
const contextValue =
|
|
933
|
+
const contextValue = React.useMemo(() => ({ ...reset, answerType }), [reset, answerType]);
|
|
923
934
|
// 分离主题相关的 props
|
|
924
|
-
const themeProps =
|
|
935
|
+
const themeProps = React.useMemo(() => ({
|
|
925
936
|
theme: props.theme || DEFAULT_THEME,
|
|
926
937
|
math: props.math,
|
|
927
938
|
codeBlock: props.codeBlock,
|
|
@@ -930,7 +941,168 @@ const Markdown = react.forwardRef((props, ref) => {
|
|
|
930
941
|
}), [props.theme, props.math, props.codeBlock, props.plugins, props.answerType]);
|
|
931
942
|
return (jsxRuntime.jsx(MarkdownProvider, { value: contextValue, children: jsxRuntime.jsx(MarkdownThemeProvider, { value: themeProps, children: jsxRuntime.jsx(MarkdownInner, { ...props, answerType: answerType, markdownRef: ref }) }) }));
|
|
932
943
|
});
|
|
933
|
-
var Markdown$1 =
|
|
944
|
+
var Markdown$1 = React.memo(Markdown);
|
|
945
|
+
|
|
946
|
+
const IconButton = ({ icon, style, className = '', onClick, ...restProps }) => {
|
|
947
|
+
return jsxRuntime.jsx(Button, { icon: icon, className: `ds-icon-button ${className}`, style: style, onClick: onClick, ...restProps });
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
const ToolTip = React.forwardRef(({ title, children, position = 'top', className = '', style, showArrow = true, delay = 200 }, ref) => {
|
|
951
|
+
const [isVisible, setIsVisible] = React.useState(false);
|
|
952
|
+
const [tooltipStyle, setTooltipStyle] = React.useState({});
|
|
953
|
+
const triggerRef = React.useRef(null);
|
|
954
|
+
const tooltipRef = React.useRef(null);
|
|
955
|
+
const timeoutRef = React.useRef(undefined);
|
|
956
|
+
// 转发ref到trigger元素
|
|
957
|
+
React.useImperativeHandle(ref, () => triggerRef.current, []);
|
|
958
|
+
const showTooltip = React.useCallback(() => {
|
|
959
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
960
|
+
setIsVisible(true);
|
|
961
|
+
}, delay);
|
|
962
|
+
}, [delay]);
|
|
963
|
+
const hideTooltip = React.useCallback(() => {
|
|
964
|
+
if (timeoutRef.current) {
|
|
965
|
+
clearTimeout(timeoutRef.current);
|
|
966
|
+
}
|
|
967
|
+
setIsVisible(false);
|
|
968
|
+
}, []);
|
|
969
|
+
const updatePosition = React.useCallback(() => {
|
|
970
|
+
if (!triggerRef.current || !tooltipRef.current)
|
|
971
|
+
return;
|
|
972
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
973
|
+
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
974
|
+
let top = 0;
|
|
975
|
+
let left = 0;
|
|
976
|
+
switch (position) {
|
|
977
|
+
case 'top':
|
|
978
|
+
top = triggerRect.top - tooltipRect.height - 8;
|
|
979
|
+
left = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
|
|
980
|
+
break;
|
|
981
|
+
case 'bottom':
|
|
982
|
+
top = triggerRect.bottom + 8;
|
|
983
|
+
left = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
|
|
984
|
+
break;
|
|
985
|
+
case 'left':
|
|
986
|
+
top = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
|
|
987
|
+
left = triggerRect.left - tooltipRect.width - 8;
|
|
988
|
+
break;
|
|
989
|
+
case 'right':
|
|
990
|
+
top = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
|
|
991
|
+
left = triggerRect.right + 8;
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
setTooltipStyle({
|
|
995
|
+
position: 'fixed',
|
|
996
|
+
top: `${top}px`,
|
|
997
|
+
left: `${left}px`,
|
|
998
|
+
zIndex: 1000,
|
|
999
|
+
});
|
|
1000
|
+
}, [position]);
|
|
1001
|
+
React.useEffect(() => {
|
|
1002
|
+
if (isVisible) {
|
|
1003
|
+
updatePosition();
|
|
1004
|
+
}
|
|
1005
|
+
}, [isVisible, position, updatePosition]);
|
|
1006
|
+
React.useEffect(() => {
|
|
1007
|
+
const handleScroll = () => {
|
|
1008
|
+
if (isVisible) {
|
|
1009
|
+
updatePosition();
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
const handleResize = () => {
|
|
1013
|
+
if (isVisible) {
|
|
1014
|
+
updatePosition();
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
window.addEventListener('scroll', handleScroll, true);
|
|
1018
|
+
window.addEventListener('resize', handleResize);
|
|
1019
|
+
return () => {
|
|
1020
|
+
window.removeEventListener('scroll', handleScroll, true);
|
|
1021
|
+
window.removeEventListener('resize', handleResize);
|
|
1022
|
+
};
|
|
1023
|
+
}, [isVisible, updatePosition]);
|
|
1024
|
+
React.useEffect(() => {
|
|
1025
|
+
return () => {
|
|
1026
|
+
if (timeoutRef.current) {
|
|
1027
|
+
clearTimeout(timeoutRef.current);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
}, []);
|
|
1031
|
+
const renderTooltip = () => {
|
|
1032
|
+
if (!isVisible)
|
|
1033
|
+
return null;
|
|
1034
|
+
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}`) })] }));
|
|
1035
|
+
return reactDom.createPortal(tooltipElement, document.body);
|
|
1036
|
+
};
|
|
1037
|
+
// 合并原有的事件处理器
|
|
1038
|
+
const handleMouseEnter = React.useCallback((e) => {
|
|
1039
|
+
e.stopPropagation(); // 阻止事件冒泡
|
|
1040
|
+
showTooltip();
|
|
1041
|
+
// 只在子元素有onMouseEnter时才调用
|
|
1042
|
+
const props = children.props;
|
|
1043
|
+
if (props.onMouseEnter) {
|
|
1044
|
+
props.onMouseEnter(e);
|
|
1045
|
+
}
|
|
1046
|
+
}, [children.props, showTooltip]);
|
|
1047
|
+
const handleMouseLeave = React.useCallback((e) => {
|
|
1048
|
+
e.stopPropagation(); // 阻止事件冒泡
|
|
1049
|
+
hideTooltip();
|
|
1050
|
+
// 只在子元素有onMouseLeave时才调用
|
|
1051
|
+
const props = children.props;
|
|
1052
|
+
if (props.onMouseLeave) {
|
|
1053
|
+
props.onMouseLeave(e);
|
|
1054
|
+
}
|
|
1055
|
+
}, [children.props, hideTooltip]);
|
|
1056
|
+
const handleFocus = React.useCallback((e) => {
|
|
1057
|
+
e.stopPropagation(); // 阻止事件冒泡
|
|
1058
|
+
showTooltip();
|
|
1059
|
+
// 只在子元素有onFocus时才调用
|
|
1060
|
+
const props = children.props;
|
|
1061
|
+
if (props.onFocus) {
|
|
1062
|
+
props.onFocus(e);
|
|
1063
|
+
}
|
|
1064
|
+
}, [children.props, showTooltip]);
|
|
1065
|
+
const handleBlur = React.useCallback((e) => {
|
|
1066
|
+
e.stopPropagation(); // 阻止事件冒泡
|
|
1067
|
+
hideTooltip();
|
|
1068
|
+
// 只在子元素有onBlur时才调用
|
|
1069
|
+
const props = children.props;
|
|
1070
|
+
if (props.onBlur) {
|
|
1071
|
+
props.onBlur(e);
|
|
1072
|
+
}
|
|
1073
|
+
}, [children.props, hideTooltip]);
|
|
1074
|
+
// 处理onClick事件
|
|
1075
|
+
const handleClick = React.useCallback((e) => {
|
|
1076
|
+
// 调用原有的onClick
|
|
1077
|
+
const props = children.props;
|
|
1078
|
+
if (props.onClick) {
|
|
1079
|
+
props.onClick(e);
|
|
1080
|
+
}
|
|
1081
|
+
}, [children.props]);
|
|
1082
|
+
// 检查组件是否支持ref
|
|
1083
|
+
const isForwardRef = React.isValidElement(children) &&
|
|
1084
|
+
typeof children.type === 'function' &&
|
|
1085
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1086
|
+
children.type.$$typeof === Symbol.for('react.forward_ref');
|
|
1087
|
+
// 如果组件不支持ref,使用包装div的方式
|
|
1088
|
+
if (!isForwardRef && typeof children.type === 'function') {
|
|
1089
|
+
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()] }));
|
|
1090
|
+
}
|
|
1091
|
+
// 使用 cloneElement 直接给子元素添加事件监听器和ref
|
|
1092
|
+
const enhancedChild = React.cloneElement(children, {
|
|
1093
|
+
ref: triggerRef,
|
|
1094
|
+
className: classNames(children.props.className, className),
|
|
1095
|
+
style: { ...children.props.style, ...style },
|
|
1096
|
+
onMouseEnter: handleMouseEnter,
|
|
1097
|
+
onMouseLeave: handleMouseLeave,
|
|
1098
|
+
onFocus: handleFocus,
|
|
1099
|
+
onBlur: handleBlur,
|
|
1100
|
+
onClick: handleClick,
|
|
1101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1102
|
+
});
|
|
1103
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [enhancedChild, renderTooltip()] }));
|
|
1104
|
+
});
|
|
1105
|
+
ToolTip.displayName = 'ToolTip';
|
|
934
1106
|
|
|
935
1107
|
/* eslint-disable react-refresh/only-export-components */
|
|
936
1108
|
|
|
@@ -940,8 +1112,11 @@ exports.CodeBlockWrap = CodeBlockWrap;
|
|
|
940
1112
|
exports.ConfigProvider = ConfigProvider;
|
|
941
1113
|
exports.CopyButton = CopyButton;
|
|
942
1114
|
exports.DownloadButton = DownloadButton;
|
|
1115
|
+
exports.HighlightCode = HighlightCode;
|
|
1116
|
+
exports.IconButton = IconButton;
|
|
943
1117
|
exports.Markdown = Markdown$1;
|
|
944
1118
|
exports.MarkdownCMD = MarkdownCMD;
|
|
1119
|
+
exports.ToolTip = ToolTip;
|
|
945
1120
|
exports.default = Markdown$1;
|
|
946
1121
|
exports.useConfig = useConfig;
|
|
947
1122
|
exports.useLocale = useLocale;
|