@lobehub/ui 5.1.1 → 5.2.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 (146) 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/EmojiPicker/EmojiPicker.d.mts +2 -2
  24. package/es/Flex/FlexBasic.d.mts +2 -2
  25. package/es/FontLoader/index.d.mts +2 -2
  26. package/es/Footer/Footer.d.mts +2 -2
  27. package/es/Form/components/FormGroup.d.mts +2 -2
  28. package/es/Form/components/FormItem.d.mts +2 -2
  29. package/es/Form/components/FormSubmitFooter.d.mts +2 -2
  30. package/es/FormModal/FormModal.d.mts +2 -2
  31. package/es/GuideCard/GuideCard.d.mts +2 -2
  32. package/es/Header/Header.d.mts +2 -2
  33. package/es/Highlighter/Highlighter.d.mts +2 -2
  34. package/es/Highlighter/SyntaxHighlighter/index.d.mts +2 -2
  35. package/es/Hotkey/Hotkey.d.mts +2 -2
  36. package/es/HotkeyInput/HotkeyInput.d.mts +2 -2
  37. package/es/Icon/Icon.d.mts +2 -2
  38. package/es/Icon/components/IconProvider.d.mts +3 -3
  39. package/es/Image/PreviewGroup.d.mts +2 -2
  40. package/es/ImageSelect/ImageSelect.d.mts +2 -2
  41. package/es/Input/Input.d.mts +2 -2
  42. package/es/Input/InputNumber.d.mts +2 -2
  43. package/es/Input/InputOPT.d.mts +2 -2
  44. package/es/Input/InputPassword.d.mts +2 -2
  45. package/es/Input/TextArea.d.mts +2 -2
  46. package/es/Layout/components/LayoutFooter.d.mts +2 -2
  47. package/es/Layout/components/LayoutHeader.d.mts +2 -2
  48. package/es/Layout/components/LayoutMain.d.mts +2 -2
  49. package/es/Layout/components/LayoutSidebar.d.mts +2 -2
  50. package/es/Layout/components/LayoutSidebarInner.d.mts +2 -2
  51. package/es/Layout/components/LayoutToc.d.mts +2 -2
  52. package/es/List/ListItem/index.d.mts +2 -2
  53. package/es/Markdown/Markdown.d.mts +2 -2
  54. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs +99 -15
  55. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs.map +1 -1
  56. package/es/Markdown/SyntaxMarkdown/style.mjs +11 -6
  57. package/es/Markdown/SyntaxMarkdown/style.mjs.map +1 -1
  58. package/es/Markdown/SyntaxMarkdown/useStreamQueue.mjs +89 -0
  59. package/es/Markdown/SyntaxMarkdown/useStreamQueue.mjs.map +1 -0
  60. package/es/Markdown/Typography.d.mts +2 -2
  61. package/es/Markdown/components/SearchResultCards/index.d.mts +2 -2
  62. package/es/Markdown/plugins/rehypeStreamAnimated.d.mts +6 -1
  63. package/es/Markdown/plugins/rehypeStreamAnimated.mjs +57 -26
  64. package/es/Markdown/plugins/rehypeStreamAnimated.mjs.map +1 -1
  65. package/es/MaskShadow/MaskShadow.d.mts +2 -2
  66. package/es/Menu/Menu.d.mts +2 -2
  67. package/es/Mermaid/Mermaid.d.mts +2 -2
  68. package/es/Mermaid/SyntaxMermaid/index.d.mts +2 -2
  69. package/es/Modal/Modal.d.mts +2 -2
  70. package/es/Modal/ModalProvider.d.mts +2 -2
  71. package/es/Modal/imperative.d.mts +2 -2
  72. package/es/MotionProvider/index.d.mts +2 -2
  73. package/es/Popover/ArrowIcon.d.mts +2 -2
  74. package/es/Popover/atoms.d.mts +9 -9
  75. package/es/Popover/context.d.mts +2 -2
  76. package/es/SearchBar/SearchBar.d.mts +2 -2
  77. package/es/Segmented/Segmented.d.mts +2 -2
  78. package/es/Select/Select.d.mts +2 -2
  79. package/es/SideNav/SideNav.d.mts +2 -2
  80. package/es/SliderWithInput/SliderWithInput.d.mts +2 -2
  81. package/es/SortableList/components/DragHandle.d.mts +2 -2
  82. package/es/SortableList/components/SortableItem.d.mts +2 -2
  83. package/es/ThemeProvider/ThemeProvider.d.mts +2 -2
  84. package/es/Toc/Toc.d.mts +2 -2
  85. package/es/Video/index.d.mts +2 -2
  86. package/es/awesome/AuroraBackground/AuroraBackground.d.mts +2 -2
  87. package/es/awesome/BottomGradientButton/BottomGradientButton.d.mts +2 -2
  88. package/es/awesome/Features/Features.d.mts +2 -2
  89. package/es/awesome/Giscus/Giscus.d.mts +2 -2
  90. package/es/awesome/GradientButton/GradientButton.d.mts +2 -2
  91. package/es/awesome/GridBackground/GridBackground.d.mts +2 -2
  92. package/es/awesome/GridBackground/GridShowcase.d.mts +2 -2
  93. package/es/awesome/Hero/Hero.d.mts +2 -2
  94. package/es/awesome/Spline/Spine.d.mts +2 -2
  95. package/es/awesome/Spotlight/Spotlight.d.mts +2 -2
  96. package/es/awesome/SpotlightCard/SpotlightCard.d.mts +2 -2
  97. package/es/awesome/TypewriterEffect/TypewriterEffect.d.mts +2 -2
  98. package/es/base-ui/DropdownMenu/DropdownMenu.d.mts +2 -2
  99. package/es/base-ui/DropdownMenu/atoms.d.mts +18 -18
  100. package/es/base-ui/Modal/context.d.mts +2 -2
  101. package/es/base-ui/Modal/imperative.d.mts +2 -2
  102. package/es/base-ui/ScrollArea/atoms.d.mts +7 -7
  103. package/es/base-ui/Select/Select.d.mts +2 -2
  104. package/es/base-ui/Select/atoms.d.mts +3 -3
  105. package/es/base-ui/Switch/Switch.d.mts +2 -2
  106. package/es/base-ui/Toast/imperative.d.mts +2 -2
  107. package/es/brand/LobeChat/index.d.mts +2 -2
  108. package/es/brand/LobeHub/index.d.mts +2 -2
  109. package/es/brand/LogoThree/LogoSpline.d.mts +2 -2
  110. package/es/brand/LogoThree/index.d.mts +2 -2
  111. package/es/chat/BackBottom/BackBottom.d.mts +2 -2
  112. package/es/chat/ChatInputArea/components/ChatInputAreaInner.d.mts +2 -2
  113. package/es/chat/ChatItem/ChatItem.d.mts +2 -2
  114. package/es/chat/ChatList/ChatList.d.mts +2 -2
  115. package/es/chat/EditableMessage/EditableMessage.d.mts +2 -2
  116. package/es/chat/EditableMessageList/EditableMessageList.d.mts +2 -2
  117. package/es/chat/MessageInput/MessageInput.d.mts +2 -2
  118. package/es/chat/MessageModal/MessageModal.d.mts +2 -2
  119. package/es/color/ColorScales/index.d.mts +2 -2
  120. package/es/color/CssVar/index.d.mts +2 -2
  121. package/es/hooks/useMarkdown/useMarkdownRehypePlugins.mjs +2 -5
  122. package/es/hooks/useMarkdown/useMarkdownRehypePlugins.mjs.map +1 -1
  123. package/es/i18n/context.d.mts +2 -2
  124. package/es/icons/lucideExtra/BotPromptIcon.d.mts +2 -2
  125. package/es/icons/lucideExtra/CreateBotIcon.d.mts +2 -2
  126. package/es/icons/lucideExtra/DiscordIcon.d.mts +3 -3
  127. package/es/icons/lucideExtra/GlobeOffIcon.d.mts +2 -2
  128. package/es/icons/lucideExtra/GroupBotIcon.d.mts +3 -3
  129. package/es/icons/lucideExtra/GroupBotSquareIcon.d.mts +2 -2
  130. package/es/icons/lucideExtra/LeftClickIcon.d.mts +2 -2
  131. package/es/icons/lucideExtra/LeftDoubleClickIcon.d.mts +3 -3
  132. package/es/icons/lucideExtra/McpIcon.d.mts +2 -2
  133. package/es/icons/lucideExtra/ProviderIcon.d.mts +2 -2
  134. package/es/icons/lucideExtra/RightClickIcon.d.mts +3 -3
  135. package/es/icons/lucideExtra/RightDoubleClickIcon.d.mts +3 -3
  136. package/es/icons/lucideExtra/ShapesUploadIcon.d.mts +3 -3
  137. package/es/icons/lucideExtra/SkillsIcon.d.mts +3 -3
  138. package/es/icons/lucideExtra/TreeDownRightIcon.d.mts +3 -3
  139. package/es/icons/lucideExtra/TreeUpDownRightIcon.d.mts +3 -3
  140. package/es/index.mjs +1 -1
  141. package/es/mdx/Mdx/index.d.mts +2 -2
  142. package/es/mobile/ChatHeader/ChatHeaderTitle.d.mts +2 -2
  143. package/es/mobile/ChatInputArea/components/ChatSendButton.d.mts +2 -2
  144. package/es/mobile/TabBar/TabBar.d.mts +2 -2
  145. package/es/storybook/StoryBook/index.d.mts +2 -2
  146. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import { LayoutSidebarInnerProps } from "../type.mjs";
2
- import * as react30 from "react";
2
+ import * as react50 from "react";
3
3
 
4
4
  //#region src/Layout/components/LayoutSidebarInner.d.ts
5
- declare const LayoutSidebarInner: react30.NamedExoticComponent<LayoutSidebarInnerProps>;
5
+ declare const LayoutSidebarInner: react50.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 react31 from "react";
2
+ import * as react51 from "react";
3
3
 
4
4
  //#region src/Layout/components/LayoutToc.d.ts
5
- declare const LayoutToc: react31.NamedExoticComponent<LayoutTocProps>;
5
+ declare const LayoutToc: react51.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 react25 from "react";
2
+ import * as react29 from "react";
3
3
 
4
4
  //#region src/List/ListItem/index.d.ts
5
- declare const ListItem: react25.NamedExoticComponent<ListItemProps>;
5
+ declare const ListItem: react29.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 react24 from "react";
2
+ import * as react41 from "react";
3
3
 
4
4
  //#region src/Markdown/Markdown.d.ts
5
- declare const Markdown: react24.NamedExoticComponent<MarkdownProps>;
5
+ declare const Markdown: react41.NamedExoticComponent<MarkdownProps>;
6
6
  //#endregion
7
7
  export { Markdown };
8
8
  //# sourceMappingURL=Markdown.d.mts.map
@@ -4,45 +4,129 @@ import { useMarkdownComponents } from "../../hooks/useMarkdown/useMarkdownCompon
4
4
  import { useMarkdownContent } from "../../hooks/useMarkdown/useMarkdownContent.mjs";
5
5
  import { useMarkdownRehypePlugins } from "../../hooks/useMarkdown/useMarkdownRehypePlugins.mjs";
6
6
  import { useMarkdownRemarkPlugins } from "../../hooks/useMarkdown/useMarkdownRemarkPlugins.mjs";
7
+ import { rehypeStreamAnimated } from "../plugins/rehypeStreamAnimated.mjs";
7
8
  import { styles } from "./style.mjs";
8
- import { createElement, memo, useId, useMemo } from "react";
9
+ import { useStreamQueue } from "./useStreamQueue.mjs";
10
+ import { createElement, memo, useEffect, useId, useMemo, useRef } from "react";
9
11
  import { jsx } from "react/jsx-runtime";
10
12
  import Markdown from "react-markdown";
11
13
  import { marked } from "marked";
12
14
  import remend from "remend";
13
15
 
14
16
  //#region src/Markdown/SyntaxMarkdown/StreamdownRender.tsx
15
- const parseMarkdownIntoBlocks = (markdown) => {
16
- return marked.lexer(markdown).map((token) => token.raw);
17
+ const STREAM_CHAR_DELAY = 15;
18
+ function countChars(text) {
19
+ return [...text].length;
20
+ }
21
+ const isRecord = (value) => typeof value === "object" && value !== null;
22
+ const isDeepEqualValue = (a, b) => {
23
+ if (a === b) return true;
24
+ if (Array.isArray(a) || Array.isArray(b)) {
25
+ if (!Array.isArray(a) || !Array.isArray(b)) return false;
26
+ if (a.length !== b.length) return false;
27
+ for (let i = 0; i < a.length; i++) if (!isDeepEqualValue(a[i], b[i])) return false;
28
+ return true;
29
+ }
30
+ if (!isRecord(a) || !isRecord(b)) return false;
31
+ const keysA = Object.keys(a);
32
+ const keysB = Object.keys(b);
33
+ if (keysA.length !== keysB.length) return false;
34
+ for (const key of keysA) if (!isDeepEqualValue(a[key], b[key])) return false;
35
+ return true;
36
+ };
37
+ const isSamePlugin = (prevPlugin, nextPlugin) => {
38
+ const prevTuple = Array.isArray(prevPlugin) ? prevPlugin : [prevPlugin];
39
+ const nextTuple = Array.isArray(nextPlugin) ? nextPlugin : [nextPlugin];
40
+ if (prevTuple.length !== nextTuple.length) return false;
41
+ if (prevTuple[0] !== nextTuple[0]) return false;
42
+ return isDeepEqualValue(prevTuple.slice(1), nextTuple.slice(1));
43
+ };
44
+ const isSamePlugins = (prevPlugins, nextPlugins) => {
45
+ if (prevPlugins === nextPlugins) return true;
46
+ if (!prevPlugins || !nextPlugins) return !prevPlugins && !nextPlugins;
47
+ if (prevPlugins.length !== nextPlugins.length) return false;
48
+ for (let i = 0; i < prevPlugins.length; i++) if (!isSamePlugin(prevPlugins[i], nextPlugins[i])) return false;
49
+ return true;
50
+ };
51
+ const useStablePlugins = (plugins) => {
52
+ const stableRef = useRef(plugins);
53
+ if (!isSamePlugins(stableRef.current, plugins)) stableRef.current = plugins;
54
+ return stableRef.current;
17
55
  };
18
56
  const StreamdownBlock = memo(({ children, ...rest }) => {
19
57
  return /* @__PURE__ */ jsx(Markdown, {
20
58
  ...rest,
21
59
  children
22
60
  });
23
- }, (prevProps, nextProps) => prevProps.children === nextProps.children);
61
+ }, (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.components === nextProps.components && isSamePlugins(prevProps.rehypePlugins, nextProps.rehypePlugins) && isSamePlugins(prevProps.remarkPlugins, nextProps.remarkPlugins));
24
62
  StreamdownBlock.displayName = "StreamdownBlock";
25
63
  const StreamdownRender = memo(({ children, ...rest }) => {
26
64
  const escapedContent = useMarkdownContent(children || "");
27
65
  const components = useMarkdownComponents();
28
- const rehypePluginsList = useMarkdownRehypePlugins();
29
- const remarkPluginsList = useMarkdownRemarkPlugins();
66
+ const baseRehypePlugins = useStablePlugins(useMarkdownRehypePlugins());
67
+ const remarkPlugins = useStablePlugins(useMarkdownRemarkPlugins());
30
68
  const generatedId = useId();
31
69
  const processedContent = useMemo(() => {
32
70
  return remend(typeof escapedContent === "string" ? escapedContent : "");
33
71
  }, [escapedContent]);
34
- const blocks = useMemo(() => parseMarkdownIntoBlocks(processedContent), [processedContent]);
72
+ const blocks = useMemo(() => {
73
+ const tokens = marked.lexer(processedContent);
74
+ let offset = 0;
75
+ return tokens.map((token) => {
76
+ const block = {
77
+ content: token.raw,
78
+ startOffset: offset
79
+ };
80
+ offset += token.raw.length;
81
+ return block;
82
+ });
83
+ }, [processedContent]);
84
+ const { getBlockState, charDelay } = useStreamQueue(blocks);
85
+ const staggerPlugins = useMemo(() => [...baseRehypePlugins, [rehypeStreamAnimated, {
86
+ baseCharCount: 0,
87
+ charDelay
88
+ }]], [baseRehypePlugins, charDelay]);
89
+ const revealedPlugins = useMemo(() => [...baseRehypePlugins, [rehypeStreamAnimated, { revealed: true }]], [baseRehypePlugins]);
90
+ const prevCharCountRef = useRef(0);
91
+ const prevStreamOffsetRef = useRef(-1);
92
+ useEffect(() => {
93
+ const tailIdx = blocks.length - 1;
94
+ if (tailIdx >= 0) {
95
+ const tail = blocks[tailIdx];
96
+ if (tail.startOffset !== prevStreamOffsetRef.current) {
97
+ prevStreamOffsetRef.current = tail.startOffset;
98
+ prevCharCountRef.current = 0;
99
+ }
100
+ prevCharCountRef.current = countChars(tail.content);
101
+ } else {
102
+ prevCharCountRef.current = 0;
103
+ prevStreamOffsetRef.current = -1;
104
+ }
105
+ }, [blocks]);
35
106
  return /* @__PURE__ */ jsx("div", {
36
107
  className: styles.animated,
37
- children: blocks.map((block, index) => /* @__PURE__ */ createElement(StreamdownBlock, {
38
- ...rest,
39
- components,
40
- key: `${generatedId}-block_${index}`,
41
- rehypePlugins: rehypePluginsList,
42
- remarkPlugins: remarkPluginsList
43
- }, block))
108
+ children: blocks.map((block, index) => {
109
+ const state = getBlockState(index);
110
+ if (state === "queued") return null;
111
+ let plugins;
112
+ if (state === "streaming") {
113
+ const baseCharCount = block.startOffset === prevStreamOffsetRef.current ? prevCharCountRef.current : 0;
114
+ plugins = [...baseRehypePlugins, [rehypeStreamAnimated, {
115
+ baseCharCount,
116
+ charDelay: STREAM_CHAR_DELAY
117
+ }]];
118
+ } else if (state === "animating") plugins = staggerPlugins;
119
+ else plugins = revealedPlugins;
120
+ return /* @__PURE__ */ createElement(StreamdownBlock, {
121
+ ...rest,
122
+ components,
123
+ key: `${generatedId}-${block.startOffset}`,
124
+ rehypePlugins: plugins,
125
+ remarkPlugins
126
+ }, block.content);
127
+ })
44
128
  });
45
- }, (prevProps, nextProps) => prevProps.children === nextProps.children);
129
+ });
46
130
  StreamdownRender.displayName = "StreamdownRender";
47
131
  var StreamdownRender_default = StreamdownRender;
48
132
 
@@ -1 +1 @@
1
- {"version":3,"file":"StreamdownRender.mjs","names":[],"sources":["../../../src/Markdown/SyntaxMarkdown/StreamdownRender.tsx"],"sourcesContent":["'use client';\n\nimport { marked } from 'marked';\nimport { memo, useId, useMemo } from 'react';\nimport Markdown, { type Options } from 'react-markdown';\nimport remend from 'remend';\n\nimport {\n useMarkdownComponents,\n useMarkdownContent,\n useMarkdownRehypePlugins,\n useMarkdownRemarkPlugins,\n} from '@/hooks/useMarkdown';\n\nimport { styles } from './style';\n\nconst parseMarkdownIntoBlocks = (markdown: string): string[] => {\n const tokens = marked.lexer(markdown);\n return tokens.map((token) => token.raw);\n};\n\nconst StreamdownBlock = memo<Options>(\n ({ children, ...rest }) => {\n return <Markdown {...rest}>{children}</Markdown>;\n },\n (prevProps, nextProps) => prevProps.children === nextProps.children,\n);\n\nStreamdownBlock.displayName = 'StreamdownBlock';\n\nexport const StreamdownRender = memo<Options>(\n ({ children, ...rest }) => {\n const escapedContent = useMarkdownContent(children || '');\n const components = useMarkdownComponents();\n const rehypePluginsList = useMarkdownRehypePlugins();\n const remarkPluginsList = useMarkdownRemarkPlugins();\n const generatedId = useId();\n const processedContent = useMemo(() => {\n const content = typeof escapedContent === 'string' ? escapedContent : '';\n return remend(content);\n }, [escapedContent]);\n\n const blocks = useMemo(() => parseMarkdownIntoBlocks(processedContent), [processedContent]);\n\n return (\n <div className={styles.animated}>\n {blocks.map((block, index) => (\n <StreamdownBlock\n {...rest}\n components={components}\n key={`${generatedId}-block_${index}`}\n rehypePlugins={rehypePluginsList}\n remarkPlugins={remarkPluginsList}\n >\n {block}\n </StreamdownBlock>\n ))}\n </div>\n );\n },\n (prevProps, nextProps) => prevProps.children === nextProps.children,\n);\nStreamdownRender.displayName = 'StreamdownRender';\n\nexport default StreamdownRender;\n"],"mappings":";;;;;;;;;;;;;;AAgBA,MAAM,2BAA2B,aAA+B;AAE9D,QADe,OAAO,MAAM,SAAS,CACvB,KAAK,UAAU,MAAM,IAAI;;AAGzC,MAAM,kBAAkB,MACrB,EAAE,UAAU,GAAG,WAAW;AACzB,QAAO,oBAAC;EAAS,GAAI;EAAO;GAAoB;IAEjD,WAAW,cAAc,UAAU,aAAa,UAAU,SAC5D;AAED,gBAAgB,cAAc;AAE9B,MAAa,mBAAmB,MAC7B,EAAE,UAAU,GAAG,WAAW;CACzB,MAAM,iBAAiB,mBAAmB,YAAY,GAAG;CACzD,MAAM,aAAa,uBAAuB;CAC1C,MAAM,oBAAoB,0BAA0B;CACpD,MAAM,oBAAoB,0BAA0B;CACpD,MAAM,cAAc,OAAO;CAC3B,MAAM,mBAAmB,cAAc;AAErC,SAAO,OADS,OAAO,mBAAmB,WAAW,iBAAiB,GAChD;IACrB,CAAC,eAAe,CAAC;CAEpB,MAAM,SAAS,cAAc,wBAAwB,iBAAiB,EAAE,CAAC,iBAAiB,CAAC;AAE3F,QACE,oBAAC;EAAI,WAAW,OAAO;YACpB,OAAO,KAAK,OAAO,UAClB,8BAAC;GACC,GAAI;GACQ;GACZ,KAAK,GAAG,YAAY,SAAS;GAC7B,eAAe;GACf,eAAe;KAEd,MACe,CAClB;GACE;IAGT,WAAW,cAAc,UAAU,aAAa,UAAU,SAC5D;AACD,iBAAiB,cAAc;AAE/B,+BAAe"}
1
+ {"version":3,"file":"StreamdownRender.mjs","names":["blocks: BlockInfo[]","staggerPlugins: Pluggable[]","revealedPlugins: Pluggable[]","plugins: Pluggable[]"],"sources":["../../../src/Markdown/SyntaxMarkdown/StreamdownRender.tsx"],"sourcesContent":["'use client';\n\nimport { marked } from 'marked';\nimport { memo, useEffect, useId, useMemo, useRef } from 'react';\nimport Markdown, { type Options } from 'react-markdown';\nimport remend from 'remend';\nimport type { Pluggable, PluggableList } from 'unified';\n\nimport {\n useMarkdownComponents,\n useMarkdownContent,\n useMarkdownRehypePlugins,\n useMarkdownRemarkPlugins,\n} from '@/hooks/useMarkdown';\nimport { rehypeStreamAnimated } from '@/Markdown/plugins/rehypeStreamAnimated';\n\nimport { styles } from './style';\nimport { type BlockInfo, useStreamQueue } from './useStreamQueue';\n\nconst STREAM_CHAR_DELAY = 15;\n\nfunction countChars(text: string): number {\n return [...text].length;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null;\n\nconst isDeepEqualValue = (a: unknown, b: unknown): boolean => {\n if (a === b) return true;\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b)) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!isDeepEqualValue(a[i], b[i])) return false;\n }\n return true;\n }\n\n if (!isRecord(a) || !isRecord(b)) return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (!isDeepEqualValue(a[key], b[key])) return false;\n }\n\n return true;\n};\n\nconst isSamePlugin = (prevPlugin: Pluggable, nextPlugin: Pluggable): boolean => {\n const prevTuple = Array.isArray(prevPlugin) ? prevPlugin : [prevPlugin];\n const nextTuple = Array.isArray(nextPlugin) ? nextPlugin : [nextPlugin];\n\n if (prevTuple.length !== nextTuple.length) return false;\n if (prevTuple[0] !== nextTuple[0]) return false;\n\n return isDeepEqualValue(prevTuple.slice(1), nextTuple.slice(1));\n};\n\nconst isSamePlugins = (\n prevPlugins?: PluggableList | null,\n nextPlugins?: PluggableList | null,\n): boolean => {\n if (prevPlugins === nextPlugins) return true;\n if (!prevPlugins || !nextPlugins) return !prevPlugins && !nextPlugins;\n if (prevPlugins.length !== nextPlugins.length) return false;\n\n for (let i = 0; i < prevPlugins.length; i++) {\n if (!isSamePlugin(prevPlugins[i], nextPlugins[i])) return false;\n }\n\n return true;\n};\n\nconst useStablePlugins = (plugins: PluggableList): PluggableList => {\n const stableRef = useRef<PluggableList>(plugins);\n\n if (!isSamePlugins(stableRef.current, plugins)) {\n stableRef.current = plugins;\n }\n\n return stableRef.current;\n};\n\nconst StreamdownBlock = memo<Options>(\n ({ children, ...rest }) => {\n return <Markdown {...rest}>{children}</Markdown>;\n },\n (prevProps, nextProps) =>\n prevProps.children === nextProps.children &&\n prevProps.components === nextProps.components &&\n isSamePlugins(prevProps.rehypePlugins, nextProps.rehypePlugins) &&\n isSamePlugins(prevProps.remarkPlugins, nextProps.remarkPlugins),\n);\n\nStreamdownBlock.displayName = 'StreamdownBlock';\n\nexport const StreamdownRender = memo<Options>(({ children, ...rest }) => {\n const escapedContent = useMarkdownContent(children || '');\n const components = useMarkdownComponents();\n const baseRehypePlugins = useStablePlugins(useMarkdownRehypePlugins());\n const remarkPlugins = useStablePlugins(useMarkdownRemarkPlugins());\n const generatedId = useId();\n\n const processedContent = useMemo(() => {\n const content = typeof escapedContent === 'string' ? escapedContent : '';\n return remend(content);\n }, [escapedContent]);\n\n const blocks: BlockInfo[] = useMemo(() => {\n const tokens = marked.lexer(processedContent);\n let offset = 0;\n return tokens.map((token) => {\n const block = { content: token.raw, startOffset: offset };\n offset += token.raw.length;\n return block;\n });\n }, [processedContent]);\n\n const { getBlockState, charDelay } = useStreamQueue(blocks);\n\n const staggerPlugins: Pluggable[] = useMemo(\n () => [...baseRehypePlugins, [rehypeStreamAnimated, { baseCharCount: 0, charDelay }]],\n [baseRehypePlugins, charDelay],\n );\n\n const revealedPlugins: Pluggable[] = useMemo(\n () => [...baseRehypePlugins, [rehypeStreamAnimated, { revealed: true }]],\n [baseRehypePlugins],\n );\n\n // prevCharCount tracks the PREVIOUS render's streaming char count.\n // Updated in useEffect (after render) to avoid stale reads during\n // synchronous re-renders (e.g. useLayoutEffect auto-reveal).\n const prevCharCountRef = useRef(0);\n const prevStreamOffsetRef = useRef(-1);\n\n useEffect(() => {\n const tailIdx = blocks.length - 1;\n if (tailIdx >= 0) {\n const tail = blocks[tailIdx];\n if (tail.startOffset !== prevStreamOffsetRef.current) {\n prevStreamOffsetRef.current = tail.startOffset;\n prevCharCountRef.current = 0;\n }\n prevCharCountRef.current = countChars(tail.content);\n } else {\n prevCharCountRef.current = 0;\n prevStreamOffsetRef.current = -1;\n }\n }, [blocks]);\n\n return (\n <div className={styles.animated}>\n {blocks.map((block, index) => {\n const state = getBlockState(index);\n if (state === 'queued') return null;\n\n let plugins: Pluggable[];\n if (state === 'streaming') {\n const baseCharCount =\n block.startOffset === prevStreamOffsetRef.current ? prevCharCountRef.current : 0;\n plugins = [\n ...baseRehypePlugins,\n [rehypeStreamAnimated, { baseCharCount, charDelay: STREAM_CHAR_DELAY }],\n ];\n } else if (state === 'animating') {\n plugins = staggerPlugins;\n } else {\n plugins = revealedPlugins;\n }\n\n return (\n <StreamdownBlock\n {...rest}\n components={components}\n key={`${generatedId}-${block.startOffset}`}\n rehypePlugins={plugins}\n remarkPlugins={remarkPlugins}\n >\n {block.content}\n </StreamdownBlock>\n );\n })}\n </div>\n );\n});\n\nStreamdownRender.displayName = 'StreamdownRender';\n\nexport default StreamdownRender;\n"],"mappings":"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"}
@@ -4,15 +4,20 @@ import { createStaticStyles } from "antd-style";
4
4
  //#region src/Markdown/SyntaxMarkdown/style.ts
5
5
  const styles = createStaticStyles(({ css: css$1 }) => {
6
6
  return { animated: css$1`
7
- .animate-fade-in,
8
- .katex-html > .base,
9
- span.line > span,
10
- code:not(:has(span.line)) {
7
+ .stream-char {
8
+ opacity: 0;
9
+
10
+ animation-name: ${fadeIn};
11
+ animation-duration: 150ms;
12
+ animation-timing-function: ease-out;
13
+ animation-fill-mode: forwards;
14
+ }
15
+
16
+ .stream-char-revealed {
11
17
  opacity: 1;
12
- animation: ${fadeIn} 1s ease-in-out;
18
+ animation: none;
13
19
  }
14
20
 
15
- /* 只对 .base 级别的 span 应用流式动画,不要穿透到内部 */
16
21
  .katex-display .katex-html span {
17
22
  mask: none !important;
18
23
  animation: none !important;
@@ -1 +1 @@
1
- {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/Markdown/SyntaxMarkdown/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nimport { fadeIn } from '@/styles/animations';\n\nexport const styles = createStaticStyles(({ css }) => {\n return {\n animated: css`\n .animate-fade-in,\n .katex-html > .base,\n span.line > span,\n code:not(:has(span.line)) {\n opacity: 1;\n animation: ${fadeIn} 1s ease-in-out;\n }\n\n /* 只对 .base 级别的 span 应用流式动画,不要穿透到内部 */\n .katex-display .katex-html span {\n mask: none !important;\n animation: none !important;\n }\n `,\n };\n});\n"],"mappings":";;;;AAIA,MAAa,SAAS,oBAAoB,EAAE,iBAAU;AACpD,QAAO,EACL,UAAU,KAAG;;;;;;qBAMI,OAAO;;;;;;;;OASzB;EACD"}
1
+ {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/Markdown/SyntaxMarkdown/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nimport { fadeIn } from '@/styles/animations';\n\nexport const styles = createStaticStyles(({ css }) => {\n return {\n animated: css`\n .stream-char {\n opacity: 0;\n\n animation-name: ${fadeIn};\n animation-duration: 150ms;\n animation-timing-function: ease-out;\n animation-fill-mode: forwards;\n }\n\n .stream-char-revealed {\n opacity: 1;\n animation: none;\n }\n\n .katex-display .katex-html span {\n mask: none !important;\n animation: none !important;\n }\n `,\n };\n});\n"],"mappings":";;;;AAIA,MAAa,SAAS,oBAAoB,EAAE,iBAAU;AACpD,QAAO,EACL,UAAU,KAAG;;;;0BAIS,OAAO;;;;;;;;;;;;;;;OAgB9B;EACD"}
@@ -0,0 +1,89 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+
3
+ //#region src/Markdown/SyntaxMarkdown/useStreamQueue.ts
4
+ const BASE_DELAY = 20;
5
+ const ACCELERATION_FACTOR = .3;
6
+ const MAX_BLOCK_DURATION = 3e3;
7
+ const FADE_DURATION = 150;
8
+ function countChars(text) {
9
+ return [...text].length;
10
+ }
11
+ function computeCharDelay(queueLength, charCount) {
12
+ let delay = BASE_DELAY / (1 + queueLength * ACCELERATION_FACTOR);
13
+ delay = Math.min(delay, MAX_BLOCK_DURATION / Math.max(charCount, 1));
14
+ return delay;
15
+ }
16
+ function useStreamQueue(blocks) {
17
+ const [revealedCount, setRevealedCount] = useState(0);
18
+ const timerRef = useRef(null);
19
+ const prevBlocksLenRef = useRef(0);
20
+ const minRevealedRef = useRef(0);
21
+ if (blocks.length === 0 && prevBlocksLenRef.current !== 0) minRevealedRef.current = 0;
22
+ if (blocks.length > prevBlocksLenRef.current && prevBlocksLenRef.current > 0) {
23
+ const prevTail = prevBlocksLenRef.current - 1;
24
+ minRevealedRef.current = Math.max(minRevealedRef.current, prevTail + 1);
25
+ }
26
+ prevBlocksLenRef.current = blocks.length;
27
+ useEffect(() => {
28
+ if (blocks.length === 0) {
29
+ setRevealedCount(0);
30
+ minRevealedRef.current = 0;
31
+ if (timerRef.current) {
32
+ clearTimeout(timerRef.current);
33
+ timerRef.current = null;
34
+ }
35
+ }
36
+ }, [blocks.length]);
37
+ const effectiveRevealedCount = Math.max(revealedCount, minRevealedRef.current);
38
+ const tailIndex = blocks.length - 1;
39
+ const getBlockState = useCallback((index) => {
40
+ if (index < effectiveRevealedCount) return "revealed";
41
+ if (index === effectiveRevealedCount && index < tailIndex) return "animating";
42
+ if (index === effectiveRevealedCount && index === tailIndex) return "streaming";
43
+ return "queued";
44
+ }, [effectiveRevealedCount, tailIndex]);
45
+ const queueLength = Math.max(0, tailIndex - effectiveRevealedCount - 1);
46
+ const animatingIndex = effectiveRevealedCount < tailIndex ? effectiveRevealedCount : -1;
47
+ const animatingCharCount = animatingIndex >= 0 ? countChars(blocks[animatingIndex]?.content ?? "") : 0;
48
+ const frozenRef = useRef({
49
+ delay: BASE_DELAY,
50
+ index: -1
51
+ });
52
+ if (animatingIndex >= 0 && animatingIndex !== frozenRef.current.index) frozenRef.current = {
53
+ delay: computeCharDelay(queueLength, animatingCharCount),
54
+ index: animatingIndex
55
+ };
56
+ const charDelay = animatingIndex >= 0 ? frozenRef.current.delay : BASE_DELAY;
57
+ const onAnimationDone = useCallback(() => {
58
+ setRevealedCount(effectiveRevealedCount + 1);
59
+ }, [effectiveRevealedCount]);
60
+ useEffect(() => {
61
+ if (timerRef.current) {
62
+ clearTimeout(timerRef.current);
63
+ timerRef.current = null;
64
+ }
65
+ if (animatingIndex < 0) return;
66
+ const totalTime = Math.max(0, (animatingCharCount - 1) * charDelay) + FADE_DURATION;
67
+ timerRef.current = setTimeout(onAnimationDone, totalTime);
68
+ return () => {
69
+ if (timerRef.current) {
70
+ clearTimeout(timerRef.current);
71
+ timerRef.current = null;
72
+ }
73
+ };
74
+ }, [
75
+ animatingIndex,
76
+ animatingCharCount,
77
+ charDelay,
78
+ onAnimationDone
79
+ ]);
80
+ return {
81
+ charDelay,
82
+ getBlockState,
83
+ queueLength
84
+ };
85
+ }
86
+
87
+ //#endregion
88
+ export { useStreamQueue };
89
+ //# sourceMappingURL=useStreamQueue.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStreamQueue.mjs","names":[],"sources":["../../../src/Markdown/SyntaxMarkdown/useStreamQueue.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface BlockInfo {\n content: string;\n startOffset: number;\n}\n\nexport type BlockState = 'revealed' | 'animating' | 'streaming' | 'queued';\n\nconst BASE_DELAY = 20;\nconst ACCELERATION_FACTOR = 0.3;\nconst MAX_BLOCK_DURATION = 3000;\nconst FADE_DURATION = 150;\n\nfunction countChars(text: string): number {\n return [...text].length;\n}\n\nfunction computeCharDelay(queueLength: number, charCount: number): number {\n const acceleration = 1 + queueLength * ACCELERATION_FACTOR;\n let delay = BASE_DELAY / acceleration;\n delay = Math.min(delay, MAX_BLOCK_DURATION / Math.max(charCount, 1));\n return delay;\n}\n\nexport interface UseStreamQueueReturn {\n charDelay: number;\n getBlockState: (index: number) => BlockState;\n queueLength: number;\n}\n\nexport function useStreamQueue(blocks: BlockInfo[]): UseStreamQueueReturn {\n const [revealedCount, setRevealedCount] = useState(0);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevBlocksLenRef = useRef(0);\n const minRevealedRef = useRef(0);\n\n // Synchronous auto-reveal during render.\n // When blocks grow, the previous tail (streaming block) is instantly\n // promoted to revealed — its chars are already visible via stream-mode\n // animation. This runs during render (not in effect) so there is NO\n // intermediate frame where the old streaming block enters 'animating'\n // state and gets stagger plugins that would restart its animations.\n if (blocks.length === 0 && prevBlocksLenRef.current !== 0) {\n minRevealedRef.current = 0;\n }\n if (blocks.length > prevBlocksLenRef.current && prevBlocksLenRef.current > 0) {\n const prevTail = prevBlocksLenRef.current - 1;\n minRevealedRef.current = Math.max(minRevealedRef.current, prevTail + 1);\n }\n prevBlocksLenRef.current = blocks.length;\n\n // State reset when stream restarts (blocks empty)\n useEffect(() => {\n if (blocks.length === 0) {\n setRevealedCount(0);\n minRevealedRef.current = 0;\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }\n }, [blocks.length]);\n\n const effectiveRevealedCount = Math.max(revealedCount, minRevealedRef.current);\n const tailIndex = blocks.length - 1;\n\n const getBlockState = useCallback(\n (index: number): BlockState => {\n if (index < effectiveRevealedCount) return 'revealed';\n if (index === effectiveRevealedCount && index < tailIndex) return 'animating';\n if (index === effectiveRevealedCount && index === tailIndex) return 'streaming';\n return 'queued';\n },\n [effectiveRevealedCount, tailIndex],\n );\n\n const queueLength = Math.max(0, tailIndex - effectiveRevealedCount - 1);\n\n const animatingIndex = effectiveRevealedCount < tailIndex ? effectiveRevealedCount : -1;\n const animatingCharCount =\n animatingIndex >= 0 ? countChars(blocks[animatingIndex]?.content ?? '') : 0;\n\n // Freeze charDelay when a new block starts animating\n const frozenRef = useRef({ delay: BASE_DELAY, index: -1 });\n if (animatingIndex >= 0 && animatingIndex !== frozenRef.current.index) {\n frozenRef.current = {\n delay: computeCharDelay(queueLength, animatingCharCount),\n index: animatingIndex,\n };\n }\n const charDelay = animatingIndex >= 0 ? frozenRef.current.delay : BASE_DELAY;\n\n const onAnimationDone = useCallback(() => {\n setRevealedCount(effectiveRevealedCount + 1);\n }, [effectiveRevealedCount]);\n\n useEffect(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n\n if (animatingIndex < 0) return;\n\n const totalTime = Math.max(0, (animatingCharCount - 1) * charDelay) + FADE_DURATION;\n timerRef.current = setTimeout(onAnimationDone, totalTime);\n\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n }, [animatingIndex, animatingCharCount, charDelay, onAnimationDone]);\n\n return { charDelay, getBlockState, queueLength };\n}\n"],"mappings":";;;AASA,MAAM,aAAa;AACnB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,gBAAgB;AAEtB,SAAS,WAAW,MAAsB;AACxC,QAAO,CAAC,GAAG,KAAK,CAAC;;AAGnB,SAAS,iBAAiB,aAAqB,WAA2B;CAExE,IAAI,QAAQ,cADS,IAAI,cAAc;AAEvC,SAAQ,KAAK,IAAI,OAAO,qBAAqB,KAAK,IAAI,WAAW,EAAE,CAAC;AACpE,QAAO;;AAST,SAAgB,eAAe,QAA2C;CACxE,MAAM,CAAC,eAAe,oBAAoB,SAAS,EAAE;CACrD,MAAM,WAAW,OAA6C,KAAK;CACnE,MAAM,mBAAmB,OAAO,EAAE;CAClC,MAAM,iBAAiB,OAAO,EAAE;AAQhC,KAAI,OAAO,WAAW,KAAK,iBAAiB,YAAY,EACtD,gBAAe,UAAU;AAE3B,KAAI,OAAO,SAAS,iBAAiB,WAAW,iBAAiB,UAAU,GAAG;EAC5E,MAAM,WAAW,iBAAiB,UAAU;AAC5C,iBAAe,UAAU,KAAK,IAAI,eAAe,SAAS,WAAW,EAAE;;AAEzE,kBAAiB,UAAU,OAAO;AAGlC,iBAAgB;AACd,MAAI,OAAO,WAAW,GAAG;AACvB,oBAAiB,EAAE;AACnB,kBAAe,UAAU;AACzB,OAAI,SAAS,SAAS;AACpB,iBAAa,SAAS,QAAQ;AAC9B,aAAS,UAAU;;;IAGtB,CAAC,OAAO,OAAO,CAAC;CAEnB,MAAM,yBAAyB,KAAK,IAAI,eAAe,eAAe,QAAQ;CAC9E,MAAM,YAAY,OAAO,SAAS;CAElC,MAAM,gBAAgB,aACnB,UAA8B;AAC7B,MAAI,QAAQ,uBAAwB,QAAO;AAC3C,MAAI,UAAU,0BAA0B,QAAQ,UAAW,QAAO;AAClE,MAAI,UAAU,0BAA0B,UAAU,UAAW,QAAO;AACpE,SAAO;IAET,CAAC,wBAAwB,UAAU,CACpC;CAED,MAAM,cAAc,KAAK,IAAI,GAAG,YAAY,yBAAyB,EAAE;CAEvE,MAAM,iBAAiB,yBAAyB,YAAY,yBAAyB;CACrF,MAAM,qBACJ,kBAAkB,IAAI,WAAW,OAAO,iBAAiB,WAAW,GAAG,GAAG;CAG5E,MAAM,YAAY,OAAO;EAAE,OAAO;EAAY,OAAO;EAAI,CAAC;AAC1D,KAAI,kBAAkB,KAAK,mBAAmB,UAAU,QAAQ,MAC9D,WAAU,UAAU;EAClB,OAAO,iBAAiB,aAAa,mBAAmB;EACxD,OAAO;EACR;CAEH,MAAM,YAAY,kBAAkB,IAAI,UAAU,QAAQ,QAAQ;CAElE,MAAM,kBAAkB,kBAAkB;AACxC,mBAAiB,yBAAyB,EAAE;IAC3C,CAAC,uBAAuB,CAAC;AAE5B,iBAAgB;AACd,MAAI,SAAS,SAAS;AACpB,gBAAa,SAAS,QAAQ;AAC9B,YAAS,UAAU;;AAGrB,MAAI,iBAAiB,EAAG;EAExB,MAAM,YAAY,KAAK,IAAI,IAAI,qBAAqB,KAAK,UAAU,GAAG;AACtE,WAAS,UAAU,WAAW,iBAAiB,UAAU;AAEzD,eAAa;AACX,OAAI,SAAS,SAAS;AACpB,iBAAa,SAAS,QAAQ;AAC9B,aAAS,UAAU;;;IAGtB;EAAC;EAAgB;EAAoB;EAAW;EAAgB,CAAC;AAEpE,QAAO;EAAE;EAAW;EAAe;EAAa"}
@@ -1,8 +1,8 @@
1
1
  import { TypographyProps } from "./type.mjs";
2
- import * as react23 from "react";
2
+ import * as react40 from "react";
3
3
 
4
4
  //#region src/Markdown/Typography.d.ts
5
- declare const Typography: react23.NamedExoticComponent<TypographyProps>;
5
+ declare const Typography: react40.NamedExoticComponent<TypographyProps>;
6
6
  //#endregion
7
7
  export { Typography };
8
8
  //# sourceMappingURL=Typography.d.mts.map
@@ -1,6 +1,6 @@
1
1
  import { FlexboxProps } from "../../../Flex/type.mjs";
2
2
  import "../../../Flex/index.mjs";
3
- import * as react77 from "react";
3
+ import * as react5 from "react";
4
4
  import { Ref } from "react";
5
5
 
6
6
  //#region src/Markdown/components/SearchResultCards/index.d.ts
@@ -14,7 +14,7 @@ interface SearchResultCardsProps extends FlexboxProps {
14
14
  dataSource: string[] | SearchResultItem[];
15
15
  ref?: Ref<HTMLDivElement>;
16
16
  }
17
- declare const SearchResultCards: react77.NamedExoticComponent<SearchResultCardsProps>;
17
+ declare const SearchResultCards: react5.NamedExoticComponent<SearchResultCardsProps>;
18
18
  //#endregion
19
19
  export { SearchResultCards, SearchResultCardsProps };
20
20
  //# sourceMappingURL=index.d.mts.map
@@ -1,7 +1,12 @@
1
1
  import { Root } from "hast";
2
2
 
3
3
  //#region src/Markdown/plugins/rehypeStreamAnimated.d.ts
4
- declare const rehypeStreamAnimated: () => (tree: Root) => void;
4
+ interface StreamAnimatedOptions {
5
+ baseCharCount?: number;
6
+ charDelay?: number;
7
+ revealed?: boolean;
8
+ }
9
+ declare const rehypeStreamAnimated: (options?: StreamAnimatedOptions) => (tree: Root) => void;
5
10
  //#endregion
6
11
  export { rehypeStreamAnimated };
7
12
  //# sourceMappingURL=rehypeStreamAnimated.d.mts.map
@@ -1,34 +1,65 @@
1
1
  import { visit } from "../../node_modules/unist-util-visit/lib/index.mjs";
2
2
 
3
3
  //#region src/Markdown/plugins/rehypeStreamAnimated.ts
4
- const rehypeStreamAnimated = () => {
4
+ const BLOCK_TAGS = new Set([
5
+ "p",
6
+ "h1",
7
+ "h2",
8
+ "h3",
9
+ "h4",
10
+ "h5",
11
+ "h6",
12
+ "li"
13
+ ]);
14
+ const SKIP_TAGS = new Set([
15
+ "pre",
16
+ "code",
17
+ "table",
18
+ "svg"
19
+ ]);
20
+ function hasClass(node, cls) {
21
+ const cn = node.properties?.className;
22
+ if (Array.isArray(cn)) return cn.some((c) => String(c).includes(cls));
23
+ if (typeof cn === "string") return cn.includes(cls);
24
+ return false;
25
+ }
26
+ const rehypeStreamAnimated = (options = {}) => {
27
+ const { charDelay = 20, baseCharCount = 0, revealed = false } = options;
5
28
  return (tree) => {
6
- visit(tree, "element", ((node) => {
7
- if ([
8
- "p",
9
- "h1",
10
- "h2",
11
- "h3",
12
- "h4",
13
- "h5",
14
- "h6",
15
- "li",
16
- "strong"
17
- ].includes(node.tagName) && node.children) {
18
- const newChildren = [];
19
- for (const child of node.children) if (child.type === "text") [...new Intl.Segmenter("zh", { granularity: "word" }).segment(child.value)].map((segment) => segment.segment).filter(Boolean).forEach((word) => {
20
- newChildren.push({
21
- children: [{
22
- type: "text",
23
- value: word
24
- }],
25
- properties: { className: "animate-fade-in" },
26
- tagName: "span",
27
- type: "element"
28
- });
29
+ let globalCharIndex = 0;
30
+ const shouldSkip = (node) => {
31
+ return SKIP_TAGS.has(node.tagName) || hasClass(node, "katex");
32
+ };
33
+ const wrapText = (node) => {
34
+ const newChildren = [];
35
+ for (const child of node.children) if (child.type === "text") for (const char of child.value) {
36
+ const properties = { className: revealed ? "stream-char stream-char-revealed" : "stream-char" };
37
+ if (!revealed) {
38
+ const delay = Math.max(0, globalCharIndex - baseCharCount) * charDelay;
39
+ if (delay > 0) properties.style = `animation-delay:${delay}ms`;
40
+ }
41
+ newChildren.push({
42
+ children: [{
43
+ type: "text",
44
+ value: char
45
+ }],
46
+ properties,
47
+ tagName: "span",
48
+ type: "element"
29
49
  });
30
- else newChildren.push(child);
31
- node.children = newChildren;
50
+ globalCharIndex++;
51
+ }
52
+ else if (child.type === "element") {
53
+ if (!shouldSkip(child)) wrapText(child);
54
+ newChildren.push(child);
55
+ } else newChildren.push(child);
56
+ node.children = newChildren;
57
+ };
58
+ visit(tree, "element", ((node) => {
59
+ if (shouldSkip(node)) return "skip";
60
+ if (BLOCK_TAGS.has(node.tagName)) {
61
+ wrapText(node);
62
+ return "skip";
32
63
  }
33
64
  }));
34
65
  };
@@ -1 +1 @@
1
- {"version":3,"file":"rehypeStreamAnimated.mjs","names":["newChildren: Array<ElementContent>"],"sources":["../../../src/Markdown/plugins/rehypeStreamAnimated.ts"],"sourcesContent":["// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n// SPDX-License-Identifier: MIT\nimport { type Element, type ElementContent, type Root } from 'hast';\nimport { type BuildVisitor } from 'unist-util-visit';\nimport { visit } from 'unist-util-visit';\n\nexport const rehypeStreamAnimated = () => {\n return (tree: Root) => {\n visit(tree, 'element', ((node: Element) => {\n if (\n ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'strong'].includes(node.tagName) &&\n node.children\n ) {\n const newChildren: Array<ElementContent> = [];\n for (const child of node.children) {\n if (child.type === 'text') {\n const segmenter = new Intl.Segmenter('zh', { granularity: 'word' });\n const segments = segmenter.segment(child.value);\n const words = [...segments].map((segment) => segment.segment).filter(Boolean);\n words.forEach((word: string) => {\n newChildren.push({\n children: [{ type: 'text', value: word }],\n properties: {\n className: 'animate-fade-in',\n },\n tagName: 'span',\n type: 'element',\n });\n });\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n }\n }) as BuildVisitor<Root, 'element'>);\n };\n};\n"],"mappings":";;;AAMA,MAAa,6BAA6B;AACxC,SAAQ,SAAe;AACrB,QAAM,MAAM,aAAa,SAAkB;AACzC,OACE;IAAC;IAAK;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAS,CAAC,SAAS,KAAK,QAAQ,IAChF,KAAK,UACL;IACA,MAAMA,cAAqC,EAAE;AAC7C,SAAK,MAAM,SAAS,KAAK,SACvB,KAAI,MAAM,SAAS,OAIjB,CADc,CAAC,GAFG,IAAI,KAAK,UAAU,MAAM,EAAE,aAAa,QAAQ,CAAC,CACxC,QAAQ,MAAM,MAAM,CACpB,CAAC,KAAK,YAAY,QAAQ,QAAQ,CAAC,OAAO,QAAQ,CACvE,SAAS,SAAiB;AAC9B,iBAAY,KAAK;MACf,UAAU,CAAC;OAAE,MAAM;OAAQ,OAAO;OAAM,CAAC;MACzC,YAAY,EACV,WAAW,mBACZ;MACD,SAAS;MACT,MAAM;MACP,CAAC;MACF;QAEF,aAAY,KAAK,MAAM;AAG3B,SAAK,WAAW;;KAEgB"}
1
+ {"version":3,"file":"rehypeStreamAnimated.mjs","names":["newChildren: ElementContent[]","properties: Record<string, any>"],"sources":["../../../src/Markdown/plugins/rehypeStreamAnimated.ts"],"sourcesContent":["import { type Element, type ElementContent, type Root } from 'hast';\nimport { type BuildVisitor } from 'unist-util-visit';\nimport { visit } from 'unist-util-visit';\n\nexport interface StreamAnimatedOptions {\n baseCharCount?: number;\n charDelay?: number;\n revealed?: boolean;\n}\n\nconst BLOCK_TAGS = new Set(['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li']);\nconst SKIP_TAGS = new Set(['pre', 'code', 'table', 'svg']);\n\nfunction hasClass(node: Element, cls: string): boolean {\n const cn = node.properties?.className;\n if (Array.isArray(cn)) return cn.some((c) => String(c).includes(cls));\n if (typeof cn === 'string') return cn.includes(cls);\n return false;\n}\n\nexport const rehypeStreamAnimated = (options: StreamAnimatedOptions = {}) => {\n const { charDelay = 20, baseCharCount = 0, revealed = false } = options;\n\n return (tree: Root) => {\n let globalCharIndex = 0;\n\n const shouldSkip = (node: Element): boolean => {\n return SKIP_TAGS.has(node.tagName) || hasClass(node, 'katex');\n };\n\n const wrapText = (node: Element) => {\n const newChildren: ElementContent[] = [];\n for (const child of node.children) {\n if (child.type === 'text') {\n for (const char of child.value) {\n const properties: Record<string, any> = {\n className: revealed ? 'stream-char stream-char-revealed' : 'stream-char',\n };\n if (!revealed) {\n const relativeIndex = Math.max(0, globalCharIndex - baseCharCount);\n const delay = relativeIndex * charDelay;\n if (delay > 0) {\n properties.style = `animation-delay:${delay}ms`;\n }\n }\n newChildren.push({\n children: [{ type: 'text', value: char }],\n properties,\n tagName: 'span',\n type: 'element',\n });\n globalCharIndex++;\n }\n } else if (child.type === 'element') {\n if (!shouldSkip(child)) {\n wrapText(child);\n }\n newChildren.push(child);\n } else {\n newChildren.push(child);\n }\n }\n node.children = newChildren;\n };\n\n visit(tree, 'element', ((node: Element) => {\n if (shouldSkip(node)) return 'skip';\n if (BLOCK_TAGS.has(node.tagName)) {\n wrapText(node);\n return 'skip';\n }\n }) as BuildVisitor<Root, 'element'>);\n };\n};\n"],"mappings":";;;AAUA,MAAM,aAAa,IAAI,IAAI;CAAC;CAAK;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAK,CAAC;AAC3E,MAAM,YAAY,IAAI,IAAI;CAAC;CAAO;CAAQ;CAAS;CAAM,CAAC;AAE1D,SAAS,SAAS,MAAe,KAAsB;CACrD,MAAM,KAAK,KAAK,YAAY;AAC5B,KAAI,MAAM,QAAQ,GAAG,CAAE,QAAO,GAAG,MAAM,MAAM,OAAO,EAAE,CAAC,SAAS,IAAI,CAAC;AACrE,KAAI,OAAO,OAAO,SAAU,QAAO,GAAG,SAAS,IAAI;AACnD,QAAO;;AAGT,MAAa,wBAAwB,UAAiC,EAAE,KAAK;CAC3E,MAAM,EAAE,YAAY,IAAI,gBAAgB,GAAG,WAAW,UAAU;AAEhE,SAAQ,SAAe;EACrB,IAAI,kBAAkB;EAEtB,MAAM,cAAc,SAA2B;AAC7C,UAAO,UAAU,IAAI,KAAK,QAAQ,IAAI,SAAS,MAAM,QAAQ;;EAG/D,MAAM,YAAY,SAAkB;GAClC,MAAMA,cAAgC,EAAE;AACxC,QAAK,MAAM,SAAS,KAAK,SACvB,KAAI,MAAM,SAAS,OACjB,MAAK,MAAM,QAAQ,MAAM,OAAO;IAC9B,MAAMC,aAAkC,EACtC,WAAW,WAAW,qCAAqC,eAC5D;AACD,QAAI,CAAC,UAAU;KAEb,MAAM,QADgB,KAAK,IAAI,GAAG,kBAAkB,cAAc,GACpC;AAC9B,SAAI,QAAQ,EACV,YAAW,QAAQ,mBAAmB,MAAM;;AAGhD,gBAAY,KAAK;KACf,UAAU,CAAC;MAAE,MAAM;MAAQ,OAAO;MAAM,CAAC;KACzC;KACA,SAAS;KACT,MAAM;KACP,CAAC;AACF;;YAEO,MAAM,SAAS,WAAW;AACnC,QAAI,CAAC,WAAW,MAAM,CACpB,UAAS,MAAM;AAEjB,gBAAY,KAAK,MAAM;SAEvB,aAAY,KAAK,MAAM;AAG3B,QAAK,WAAW;;AAGlB,QAAM,MAAM,aAAa,SAAkB;AACzC,OAAI,WAAW,KAAK,CAAE,QAAO;AAC7B,OAAI,WAAW,IAAI,KAAK,QAAQ,EAAE;AAChC,aAAS,KAAK;AACd,WAAO;;KAEyB"}
@@ -1,8 +1,8 @@
1
1
  import { MaskShadowProps } from "./type.mjs";
2
- import * as react32 from "react";
2
+ import * as react44 from "react";
3
3
 
4
4
  //#region src/MaskShadow/MaskShadow.d.ts
5
- declare const MaskShadow: react32.NamedExoticComponent<MaskShadowProps>;
5
+ declare const MaskShadow: react44.NamedExoticComponent<MaskShadowProps>;
6
6
  //#endregion
7
7
  export { MaskShadow };
8
8
  //# sourceMappingURL=MaskShadow.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { MenuProps } from "./type.mjs";
2
- import * as react22 from "react";
2
+ import * as react45 from "react";
3
3
 
4
4
  //#region src/Menu/Menu.d.ts
5
- declare const Menu: react22.NamedExoticComponent<MenuProps<unknown>>;
5
+ declare const Menu: react45.NamedExoticComponent<MenuProps<unknown>>;
6
6
  //#endregion
7
7
  export { Menu };
8
8
  //# sourceMappingURL=Menu.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { MermaidProps } from "./type.mjs";
2
- import * as react20 from "react";
2
+ import * as react43 from "react";
3
3
 
4
4
  //#region src/Mermaid/Mermaid.d.ts
5
- declare const Mermaid: react20.NamedExoticComponent<MermaidProps>;
5
+ declare const Mermaid: react43.NamedExoticComponent<MermaidProps>;
6
6
  //#endregion
7
7
  export { Mermaid };
8
8
  //# sourceMappingURL=Mermaid.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { SyntaxMermaidProps } from "../type.mjs";
2
- import * as react21 from "react";
2
+ import * as react42 from "react";
3
3
 
4
4
  //#region src/Mermaid/SyntaxMermaid/index.d.ts
5
- declare const SyntaxMermaid: react21.NamedExoticComponent<SyntaxMermaidProps>;
5
+ declare const SyntaxMermaid: react42.NamedExoticComponent<SyntaxMermaidProps>;
6
6
  //#endregion
7
7
  export { SyntaxMermaid };
8
8
  //# sourceMappingURL=index.d.mts.map
@@ -1,8 +1,8 @@
1
1
  import { ModalProps } from "./type.mjs";
2
- import * as react13 from "react";
2
+ import * as react37 from "react";
3
3
 
4
4
  //#region src/Modal/Modal.d.ts
5
- declare const Modal: react13.NamedExoticComponent<ModalProps>;
5
+ declare const Modal: react37.NamedExoticComponent<ModalProps>;
6
6
  //#endregion
7
7
  export { Modal };
8
8
  //# sourceMappingURL=Modal.d.mts.map
@@ -1,9 +1,9 @@
1
1
  import { ModalContextValue } from "./type.mjs";
2
- import * as react14 from "react";
2
+ import * as react38 from "react";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/Modal/ModalProvider.d.ts
6
- declare const ModalProvider: react14.NamedExoticComponent<{
6
+ declare const ModalProvider: react38.NamedExoticComponent<{
7
7
  children: ReactNode;
8
8
  value: ModalContextValue;
9
9
  }>;
@@ -1,5 +1,5 @@
1
1
  import { ImperativeModalProps, ModalInstance, RawModalComponent, RawModalComponentProps, RawModalInstance, RawModalKeyOptions, RawModalOptions } from "./type.mjs";
2
- import * as react_jsx_runtime11 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime18 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/Modal/imperative.d.ts
5
5
  type ModalHostProps = {
@@ -7,7 +7,7 @@ type ModalHostProps = {
7
7
  };
8
8
  declare const ModalHost: ({
9
9
  root
10
- }: ModalHostProps) => react_jsx_runtime11.JSX.Element | null;
10
+ }: ModalHostProps) => react_jsx_runtime18.JSX.Element | null;
11
11
  declare const createModal: (props: ImperativeModalProps) => ModalInstance;
12
12
  declare function createRawModal<P extends RawModalComponentProps>(component: RawModalComponent<P>, props: Omit<P, 'open' | 'onClose'>, options?: RawModalOptions): RawModalInstance<P>;
13
13
  declare function createRawModal<P, OpenKey extends keyof P, CloseKey extends keyof P>(component: RawModalComponent<P>, props: Omit<P, OpenKey | CloseKey>, options: RawModalKeyOptions<OpenKey, CloseKey>): RawModalInstance<P, OpenKey, CloseKey>;
@@ -1,4 +1,4 @@
1
- import * as react78 from "react";
1
+ import * as react6 from "react";
2
2
  import { Context, ReactNode } from "react";
3
3
  import * as motion_react0 from "motion/react";
4
4
  import * as m from "motion/react-m";
@@ -6,7 +6,7 @@ import * as m from "motion/react-m";
6
6
  //#region src/MotionProvider/index.d.ts
7
7
  type MotionComponentType = typeof motion_react0.motion | typeof m;
8
8
  declare const MotionComponent: Context<MotionComponentType>;
9
- declare const MotionProvider: react78.NamedExoticComponent<{
9
+ declare const MotionProvider: react6.NamedExoticComponent<{
10
10
  children: ReactNode;
11
11
  motion: MotionComponentType;
12
12
  }>;