@incremark/react 0.2.7 → 0.3.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.
- package/README.en.md +216 -47
- package/dist/index.d.ts +19 -1
- package/dist/index.js +420 -253
- package/package.json +19 -6
package/README.en.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
# @incremark/react
|
|
2
2
|
|
|
3
|
-
React 18+ integration for Incremark.
|
|
3
|
+
React 18+ integration library for Incremark, providing high-performance streaming Markdown rendering components.
|
|
4
4
|
|
|
5
5
|
**[🇨🇳 中文](./README.md)** | 🇺🇸 English
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Core Advantages
|
|
8
8
|
|
|
9
|
-
- 📦 **Out of the Box** - Provides `
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- 📦 **Out of the Box** - Provides `IncremarkContent` component and `useIncremark` hook
|
|
10
|
+
- ⚡ **Extreme Performance** - Incremental parsing with O(n) complexity, dual-engine support
|
|
11
|
+
- ⌨️ **Typewriter Effect** - Built-in animation effects (fade-in, typing)
|
|
12
|
+
- 🎨 **Highly Customizable** - Custom components, code blocks, containers
|
|
13
|
+
- 🎯 **Theme System** - Built-in ThemeProvider with light/dark themes
|
|
14
|
+
- 📜 **Auto Scroll** - Built-in AutoScrollContainer component
|
|
15
|
+
- 🔧 **DevTools** - Built-in developer debugging tools
|
|
13
16
|
|
|
14
17
|
## Installation
|
|
15
18
|
|
|
@@ -19,20 +22,63 @@ pnpm add @incremark/core @incremark/react
|
|
|
19
22
|
|
|
20
23
|
## Quick Start
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
### Recommended: IncremarkContent Component
|
|
23
26
|
|
|
24
27
|
```tsx
|
|
28
|
+
import { useState } from 'react'
|
|
29
|
+
import { IncremarkContent } from '@incremark/react'
|
|
25
30
|
import '@incremark/react/styles.css'
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
const [content, setContent] = useState('')
|
|
34
|
+
const [isFinished, setIsFinished] = useState(false)
|
|
35
|
+
|
|
36
|
+
// Handle AI streaming output
|
|
37
|
+
async function handleStream(stream: ReadableStream) {
|
|
38
|
+
setContent('')
|
|
39
|
+
setIsFinished(false)
|
|
40
|
+
|
|
41
|
+
const reader = stream.getReader()
|
|
42
|
+
const decoder = new TextDecoder()
|
|
43
|
+
|
|
44
|
+
while (true) {
|
|
45
|
+
const { done, value } = await reader.read()
|
|
46
|
+
if (done) break
|
|
47
|
+
setContent(prev => prev + decoder.decode(value))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setIsFinished(true)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<>
|
|
55
|
+
<button onClick={() => handleStream(stream)}>Start</button>
|
|
56
|
+
<IncremarkContent
|
|
57
|
+
content={content}
|
|
58
|
+
isFinished={isFinished}
|
|
59
|
+
incremarkOptions={{
|
|
60
|
+
gfm: true,
|
|
61
|
+
math: true,
|
|
62
|
+
containers: true,
|
|
63
|
+
htmlTree: true
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
</>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
26
69
|
```
|
|
27
70
|
|
|
28
|
-
|
|
71
|
+
### Advanced: useIncremark Hook
|
|
29
72
|
|
|
30
73
|
```tsx
|
|
31
74
|
import { useIncremark, Incremark } from '@incremark/react'
|
|
32
75
|
import '@incremark/react/styles.css'
|
|
33
76
|
|
|
34
77
|
function App() {
|
|
35
|
-
const { blocks, append, finalize, reset } = useIncremark({
|
|
78
|
+
const { blocks, append, finalize, reset } = useIncremark({
|
|
79
|
+
gfm: true,
|
|
80
|
+
math: true
|
|
81
|
+
})
|
|
36
82
|
|
|
37
83
|
async function handleStream(stream: ReadableStream) {
|
|
38
84
|
reset()
|
|
@@ -57,64 +103,170 @@ function App() {
|
|
|
57
103
|
}
|
|
58
104
|
```
|
|
59
105
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
|
|
106
|
+
## IncremarkContent Component
|
|
107
|
+
|
|
108
|
+
Declarative all-in-one component, recommended for most scenarios.
|
|
109
|
+
|
|
110
|
+
### Props
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
interface IncremarkContentProps {
|
|
114
|
+
// Input (choose one)
|
|
115
|
+
content?: string // Accumulated Markdown string
|
|
116
|
+
stream?: () => AsyncGenerator<string> // Async generator function
|
|
117
|
+
|
|
118
|
+
// Status
|
|
119
|
+
isFinished?: boolean // Stream finished flag (required for content mode)
|
|
120
|
+
|
|
121
|
+
// Configuration
|
|
122
|
+
incremarkOptions?: {
|
|
123
|
+
gfm?: boolean // GFM support
|
|
124
|
+
math?: boolean // Math formulas
|
|
125
|
+
htmlTree?: boolean // HTML structured parsing
|
|
126
|
+
containers?: boolean // ::: container syntax
|
|
127
|
+
typewriter?: { // Typewriter effect
|
|
128
|
+
enabled?: boolean
|
|
129
|
+
charsPerTick?: number | [number, number]
|
|
130
|
+
tickInterval?: number
|
|
131
|
+
effect?: 'none' | 'fade-in' | 'typing'
|
|
132
|
+
cursor?: string
|
|
133
|
+
}
|
|
134
|
+
}
|
|
63
135
|
|
|
64
|
-
|
|
136
|
+
// Custom rendering
|
|
137
|
+
components?: ComponentMap // Custom components
|
|
138
|
+
customContainers?: Record<string, ComponentType> // Custom containers
|
|
139
|
+
customCodeBlocks?: Record<string, ComponentType> // Custom code blocks
|
|
140
|
+
codeBlockConfigs?: Record<string, CodeBlockConfig>
|
|
65
141
|
|
|
66
|
-
|
|
142
|
+
// Styling
|
|
143
|
+
showBlockStatus?: boolean // Show block status border
|
|
144
|
+
pendingClass?: string // CSS class for pending blocks
|
|
145
|
+
}
|
|
146
|
+
```
|
|
67
147
|
|
|
68
|
-
|
|
69
|
-
|----------|------|-------------|
|
|
70
|
-
| `markdown` | `string` | Complete Markdown |
|
|
71
|
-
| `blocks` | `Block[]` | All blocks |
|
|
72
|
-
| `completedBlocks` | `Block[]` | Completed blocks |
|
|
73
|
-
| `pendingBlocks` | `Block[]` | Pending blocks |
|
|
74
|
-
| `append` | `Function` | Append content |
|
|
75
|
-
| `finalize` | `Function` | Complete parsing |
|
|
76
|
-
| `reset` | `Function` | Reset state |
|
|
77
|
-
| `render` | `Function` | Render once (reset + append + finalize) |
|
|
148
|
+
### Example: Enable Typewriter Effect
|
|
78
149
|
|
|
79
|
-
|
|
150
|
+
```tsx
|
|
151
|
+
<IncremarkContent
|
|
152
|
+
content={content}
|
|
153
|
+
isFinished={isFinished}
|
|
154
|
+
incremarkOptions={{
|
|
155
|
+
gfm: true,
|
|
156
|
+
typewriter: {
|
|
157
|
+
enabled: true,
|
|
158
|
+
charsPerTick: [1, 3],
|
|
159
|
+
tickInterval: 30,
|
|
160
|
+
effect: 'fade-in'
|
|
161
|
+
}
|
|
162
|
+
}}
|
|
163
|
+
/>
|
|
164
|
+
```
|
|
80
165
|
|
|
81
|
-
|
|
166
|
+
### Example: Custom Components
|
|
82
167
|
|
|
83
168
|
```tsx
|
|
84
|
-
|
|
85
|
-
|
|
169
|
+
import CustomHeading from './CustomHeading'
|
|
170
|
+
import WarningContainer from './WarningContainer'
|
|
171
|
+
import EchartsCodeBlock from './EchartsCodeBlock'
|
|
172
|
+
|
|
173
|
+
<IncremarkContent
|
|
174
|
+
content={content}
|
|
175
|
+
isFinished={isFinished}
|
|
176
|
+
components={{ heading: CustomHeading }}
|
|
177
|
+
customContainers={{ warning: WarningContainer }}
|
|
178
|
+
customCodeBlocks={{ echarts: EchartsCodeBlock }}
|
|
179
|
+
codeBlockConfigs={{ echarts: { takeOver: true } }}
|
|
180
|
+
/>
|
|
86
181
|
```
|
|
87
182
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Render component.
|
|
183
|
+
## Theme System
|
|
91
184
|
|
|
92
185
|
```tsx
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
186
|
+
import { ThemeProvider, IncremarkContent } from '@incremark/react'
|
|
187
|
+
|
|
188
|
+
// Built-in theme
|
|
189
|
+
<ThemeProvider theme="dark">
|
|
190
|
+
<IncremarkContent content={content} isFinished={isFinished} />
|
|
191
|
+
</ThemeProvider>
|
|
192
|
+
|
|
193
|
+
// Custom theme
|
|
194
|
+
<ThemeProvider theme={{ color: { brand: { primary: '#8b5cf6' } } }}>
|
|
195
|
+
<IncremarkContent content={content} isFinished={isFinished} />
|
|
196
|
+
</ThemeProvider>
|
|
97
197
|
```
|
|
98
198
|
|
|
99
|
-
##
|
|
199
|
+
## Auto Scroll
|
|
100
200
|
|
|
101
201
|
```tsx
|
|
102
|
-
import {
|
|
103
|
-
import
|
|
202
|
+
import { useRef, useState } from 'react'
|
|
203
|
+
import { AutoScrollContainer, IncremarkContent, type AutoScrollContainerRef } from '@incremark/react'
|
|
104
204
|
|
|
105
205
|
function App() {
|
|
106
|
-
const
|
|
107
|
-
|
|
206
|
+
const scrollRef = useRef<AutoScrollContainerRef>(null)
|
|
207
|
+
const [autoScrollEnabled, setAutoScrollEnabled] = useState(true)
|
|
208
|
+
|
|
108
209
|
return (
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
210
|
+
<div>
|
|
211
|
+
<AutoScrollContainer
|
|
212
|
+
ref={scrollRef}
|
|
213
|
+
enabled={autoScrollEnabled}
|
|
214
|
+
threshold={50}
|
|
215
|
+
behavior="smooth"
|
|
216
|
+
>
|
|
217
|
+
<IncremarkContent content={content} isFinished={isFinished} />
|
|
218
|
+
</AutoScrollContainer>
|
|
219
|
+
|
|
220
|
+
<button onClick={() => scrollRef.current?.scrollToBottom()}>
|
|
221
|
+
Scroll to Bottom
|
|
222
|
+
</button>
|
|
223
|
+
</div>
|
|
113
224
|
)
|
|
114
225
|
}
|
|
115
226
|
```
|
|
116
227
|
|
|
117
|
-
##
|
|
228
|
+
## useIncremark API
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
const {
|
|
232
|
+
// State
|
|
233
|
+
markdown, // string - Complete Markdown
|
|
234
|
+
blocks, // Block[] - All blocks
|
|
235
|
+
completedBlocks, // Block[] - Completed blocks
|
|
236
|
+
pendingBlocks, // Block[] - Pending blocks
|
|
237
|
+
isLoading, // boolean - Is loading
|
|
238
|
+
isDisplayComplete, // boolean - Is display complete
|
|
239
|
+
|
|
240
|
+
// Methods
|
|
241
|
+
append, // (chunk: string) => IncrementalUpdate
|
|
242
|
+
finalize, // () => IncrementalUpdate
|
|
243
|
+
reset, // () => void
|
|
244
|
+
render, // (content: string) => IncrementalUpdate
|
|
245
|
+
|
|
246
|
+
// Typewriter controls
|
|
247
|
+
typewriter: {
|
|
248
|
+
enabled, // boolean - Is enabled
|
|
249
|
+
isProcessing, // boolean - Is processing
|
|
250
|
+
skip, // () => void - Skip animation
|
|
251
|
+
setOptions // (options) => void - Update config
|
|
252
|
+
}
|
|
253
|
+
} = useIncremark(options)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## DevTools
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
import { useIncremark, useDevTools, Incremark } from '@incremark/react'
|
|
260
|
+
|
|
261
|
+
function App() {
|
|
262
|
+
const incremark = useIncremark()
|
|
263
|
+
useDevTools(incremark)
|
|
264
|
+
|
|
265
|
+
return <Incremark blocks={incremark.blocks} />
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## React Query Integration
|
|
118
270
|
|
|
119
271
|
```tsx
|
|
120
272
|
import { useQuery } from '@tanstack/react-query'
|
|
@@ -127,7 +279,7 @@ function StreamingContent() {
|
|
|
127
279
|
queryKey: ['chat'],
|
|
128
280
|
queryFn: async () => {
|
|
129
281
|
reset()
|
|
130
|
-
// ... streaming
|
|
282
|
+
// ... streaming logic
|
|
131
283
|
finalize()
|
|
132
284
|
return null
|
|
133
285
|
},
|
|
@@ -143,7 +295,24 @@ function StreamingContent() {
|
|
|
143
295
|
}
|
|
144
296
|
```
|
|
145
297
|
|
|
298
|
+
## Math Formula Support
|
|
299
|
+
|
|
300
|
+
Built-in support, just enable `math: true`:
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
<IncremarkContent
|
|
304
|
+
content={content}
|
|
305
|
+
isFinished={isFinished}
|
|
306
|
+
incremarkOptions={{ math: true }}
|
|
307
|
+
/>
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Import KaTeX styles:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import 'katex/dist/katex.min.css'
|
|
314
|
+
```
|
|
315
|
+
|
|
146
316
|
## License
|
|
147
317
|
|
|
148
318
|
MIT
|
|
149
|
-
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ import React$1, { ReactNode, ComponentType } from 'react';
|
|
|
4
4
|
import { Definition, FootnoteDefinition, RootContent, PhrasingContent } from 'mdast';
|
|
5
5
|
import * as _incremark_devtools from '@incremark/devtools';
|
|
6
6
|
import { DevToolsOptions } from '@incremark/devtools';
|
|
7
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
8
|
+
import { IncremarkLocale } from '@incremark/shared';
|
|
9
|
+
export { IncremarkLocale, en, zhCN } from '@incremark/shared';
|
|
7
10
|
import { DesignTokens } from '@incremark/theme';
|
|
8
11
|
export { DesignTokens, applyTheme, darkTheme, defaultTheme, generateCSSVars, mergeTheme } from '@incremark/theme';
|
|
9
12
|
|
|
@@ -293,6 +296,15 @@ interface UseBlockTransformerReturn<T = unknown> {
|
|
|
293
296
|
*/
|
|
294
297
|
declare function useBlockTransformer<T = unknown>(sourceBlocks: SourceBlock<T>[], options?: UseBlockTransformerOptions): UseBlockTransformerReturn<T>;
|
|
295
298
|
|
|
299
|
+
/**
|
|
300
|
+
* React 国际化 Hook
|
|
301
|
+
*/
|
|
302
|
+
interface UseLocaleReturn {
|
|
303
|
+
/** 翻译函数 */
|
|
304
|
+
t: (key: string) => string;
|
|
305
|
+
}
|
|
306
|
+
declare function useLocale(): UseLocaleReturn;
|
|
307
|
+
|
|
296
308
|
type ComponentMap = Partial<Record<string, ComponentType<{
|
|
297
309
|
node: any;
|
|
298
310
|
}>>>;
|
|
@@ -588,6 +600,12 @@ interface IncremarkContainerProviderProps {
|
|
|
588
600
|
*/
|
|
589
601
|
declare const IncremarkContainerProvider: React$1.FC<IncremarkContainerProviderProps>;
|
|
590
602
|
|
|
603
|
+
interface ConfigProviderProps {
|
|
604
|
+
children: ReactNode;
|
|
605
|
+
locale?: IncremarkLocale;
|
|
606
|
+
}
|
|
607
|
+
declare function ConfigProvider({ children, locale }: ConfigProviderProps): react_jsx_runtime.JSX.Element;
|
|
608
|
+
|
|
591
609
|
interface ThemeProviderProps {
|
|
592
610
|
/** 主题配置,可以是:
|
|
593
611
|
* - 字符串:'default' | 'dark'
|
|
@@ -620,4 +638,4 @@ interface ThemeProviderProps {
|
|
|
620
638
|
*/
|
|
621
639
|
declare const ThemeProvider: React$1.FC<ThemeProviderProps>;
|
|
622
640
|
|
|
623
|
-
export { AutoScrollContainer, type AutoScrollContainerProps, type AutoScrollContainerRef, type DefinitionsContextValue, DefinitionsProvider, type DefinitionsProviderProps, type HtmlElementNode, Incremark, IncremarkContainerProvider, type IncremarkContainerProviderProps, IncremarkContent, type IncremarkContentProps, IncremarkFootnotes, IncremarkHtmlElement, type IncremarkHtmlElementProps, IncremarkInline, type IncremarkInlineProps, type IncremarkProps, IncremarkRenderer, type IncremarkRendererProps, ThemeProvider, type ThemeProviderProps, type TypewriterControls, type TypewriterOptions, type UseBlockTransformerOptions, type UseBlockTransformerReturn, type UseDevToolsOptions, type UseIncremarkOptions, type UseIncremarkReturn, useBlockTransformer, useDefinitions, useDevTools, useIncremark };
|
|
641
|
+
export { AutoScrollContainer, type AutoScrollContainerProps, type AutoScrollContainerRef, ConfigProvider, type DefinitionsContextValue, DefinitionsProvider, type DefinitionsProviderProps, type HtmlElementNode, Incremark, IncremarkContainerProvider, type IncremarkContainerProviderProps, IncremarkContent, type IncremarkContentProps, IncremarkFootnotes, IncremarkHtmlElement, type IncremarkHtmlElementProps, IncremarkInline, type IncremarkInlineProps, type IncremarkProps, IncremarkRenderer, type IncremarkRendererProps, ThemeProvider, type ThemeProviderProps, type TypewriterControls, type TypewriterOptions, type UseBlockTransformerOptions, type UseBlockTransformerReturn, type UseDevToolsOptions, type UseIncremarkOptions, type UseIncremarkReturn, type UseLocaleReturn, useBlockTransformer, useDefinitions, useDevTools, useIncremark, useLocale };
|