@incremark/react 0.0.5 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,32 +1,85 @@
1
- import { ParserOptions, ParsedBlock, Root, IncrementalUpdate, IncremarkParser, SourceBlock, TransformerOptions, DisplayBlock, AnimationEffect, BlockTransformer, RootContent } from '@incremark/core';
1
+ import { ParserOptions, AnimationEffect, TransformerPlugin, ParsedBlock, Root, IncrementalUpdate, IncremarkParser, SourceBlock, TransformerOptions, DisplayBlock, BlockTransformer, RootContent } from '@incremark/core';
2
2
  export { AnimationEffect, BlockTransformer, DisplayBlock, IncrementalUpdate, ParsedBlock, ParserOptions, Root, RootContent, SourceBlock, TransformerOptions, TransformerPlugin, TransformerState, allPlugins, cloneNode, codeBlockPlugin, countChars, createBlockTransformer, createPlugin, defaultPlugins, imagePlugin, mathPlugin, mermaidPlugin, sliceAst, thematicBreakPlugin } from '@incremark/core';
3
3
  import * as _incremark_devtools from '@incremark/devtools';
4
4
  import { DevToolsOptions } from '@incremark/devtools';
5
5
  import React from 'react';
6
6
 
7
+ /** 打字机效果配置 */
8
+ interface TypewriterOptions {
9
+ /** 是否启用打字机效果(可动态切换) */
10
+ enabled?: boolean;
11
+ /** 每次显示的字符数,可以是固定值或范围 [min, max] */
12
+ charsPerTick?: number | [number, number];
13
+ /** 更新间隔 (ms) */
14
+ tickInterval?: number;
15
+ /** 动画效果: 'none' | 'fade-in' | 'typing' */
16
+ effect?: AnimationEffect;
17
+ /** 光标字符(仅 typing 效果使用) */
18
+ cursor?: string;
19
+ /** 页面不可见时暂停 */
20
+ pauseOnHidden?: boolean;
21
+ /** 自定义插件 */
22
+ plugins?: TransformerPlugin[];
23
+ }
7
24
  interface UseIncremarkOptions extends ParserOptions {
25
+ /** 打字机配置,传入即创建 transformer(可通过 enabled 控制是否启用) */
26
+ typewriter?: TypewriterOptions;
8
27
  }
9
28
  interface BlockWithStableId$1 extends ParsedBlock {
10
29
  stableId: string;
11
30
  }
31
+ /** 打字机控制对象 */
32
+ interface TypewriterControls {
33
+ /** 是否启用 */
34
+ enabled: boolean;
35
+ /** 设置启用状态 */
36
+ setEnabled: (enabled: boolean) => void;
37
+ /** 是否正在处理中 */
38
+ isProcessing: boolean;
39
+ /** 是否已暂停 */
40
+ isPaused: boolean;
41
+ /** 当前动画效果 */
42
+ effect: AnimationEffect;
43
+ /** 跳过动画,直接显示全部 */
44
+ skip: () => void;
45
+ /** 暂停动画 */
46
+ pause: () => void;
47
+ /** 恢复动画 */
48
+ resume: () => void;
49
+ /** 动态更新配置 */
50
+ setOptions: (options: Partial<TypewriterOptions>) => void;
51
+ }
12
52
  /**
13
53
  * React Hook: Incremark 流式 Markdown 解析器
14
54
  *
15
55
  * @example
16
56
  * ```tsx
17
- * import { useIncremark } from '@incremark/react'
57
+ * import { useIncremark, Incremark } from '@incremark/react'
18
58
  *
19
59
  * function App() {
20
- * const { markdown, blocks, append, finalize, reset } = useIncremark()
60
+ * // 基础用法
61
+ * const { blocks, append, finalize } = useIncremark()
21
62
  *
22
- * async function handleStream(stream) {
23
- * for await (const chunk of stream) {
24
- * append(chunk)
63
+ * // 启用打字机效果
64
+ * const { blocks, append, finalize, typewriter } = useIncremark({
65
+ * typewriter: {
66
+ * enabled: true, // 可动态切换
67
+ * charsPerTick: [1, 3],
68
+ * tickInterval: 30,
69
+ * effect: 'typing',
70
+ * cursor: '|'
25
71
  * }
26
- * finalize()
27
- * }
72
+ * })
73
+ *
74
+ * // 动态切换打字机效果
75
+ * typewriter.setEnabled(false)
28
76
  *
29
- * return <div>{markdown.length} 字符</div>
77
+ * return (
78
+ * <>
79
+ * <Incremark blocks={blocks} />
80
+ * {typewriter.isProcessing && <button onClick={typewriter.skip}>跳过</button>}
81
+ * </>
82
+ * )
30
83
  * }
31
84
  * ```
32
85
  */
@@ -39,7 +92,7 @@ declare function useIncremark(options?: UseIncremarkOptions): {
39
92
  pendingBlocks: ParsedBlock[];
40
93
  /** 当前完整的 AST */
41
94
  ast: Root;
42
- /** 所有块(完成 + 待处理),带稳定 ID */
95
+ /** 用于渲染的 blocks(根据打字机设置自动处理) */
43
96
  blocks: BlockWithStableId$1[];
44
97
  /** 是否正在加载 */
45
98
  isLoading: boolean;
@@ -49,12 +102,14 @@ declare function useIncremark(options?: UseIncremarkOptions): {
49
102
  finalize: () => IncrementalUpdate;
50
103
  /** 强制中断 */
51
104
  abort: () => IncrementalUpdate;
52
- /** 重置解析器 */
105
+ /** 重置解析器和打字机 */
53
106
  reset: () => void;
54
107
  /** 一次性渲染(reset + append + finalize) */
55
108
  render: (content: string) => IncrementalUpdate;
56
109
  /** 解析器实例 */
57
110
  parser: IncremarkParser;
111
+ /** 打字机控制 */
112
+ typewriter: TypewriterControls;
58
113
  };
59
114
  type UseIncremarkReturn = ReturnType<typeof useIncremark>;
60
115
 
@@ -180,7 +235,7 @@ declare const Incremark: React.FC<IncremarkProps>;
180
235
  interface IncremarkRendererProps {
181
236
  node: RootContent;
182
237
  components?: Partial<Record<string, React.ComponentType<{
183
- node: any;
238
+ node: RootContent;
184
239
  }>>>;
185
240
  }
186
241
  /**
@@ -230,4 +285,4 @@ interface AutoScrollContainerRef {
230
285
  */
231
286
  declare const AutoScrollContainer: React.ForwardRefExoticComponent<AutoScrollContainerProps & React.RefAttributes<AutoScrollContainerRef>>;
232
287
 
233
- export { AutoScrollContainer, type AutoScrollContainerProps, type AutoScrollContainerRef, Incremark, type IncremarkProps, IncremarkRenderer, type IncremarkRendererProps, type UseBlockTransformerOptions, type UseBlockTransformerReturn, type UseDevToolsOptions, type UseIncremarkOptions, type UseIncremarkReturn, useBlockTransformer, useDevTools, useIncremark };
288
+ export { AutoScrollContainer, type AutoScrollContainerProps, type AutoScrollContainerRef, Incremark, type IncremarkProps, IncremarkRenderer, type IncremarkRendererProps, type TypewriterControls, type TypewriterOptions, type UseBlockTransformerOptions, type UseBlockTransformerReturn, type UseDevToolsOptions, type UseIncremarkOptions, type UseIncremarkReturn, useBlockTransformer, useDevTools, useIncremark };
package/dist/index.js CHANGED
@@ -1,31 +1,125 @@
1
1
  // src/hooks/useIncremark.ts
2
- import { useState, useCallback, useMemo, useRef } from "react";
2
+ import { useState, useCallback, useMemo, useRef, useEffect } from "react";
3
3
  import {
4
- createIncremarkParser
4
+ createIncremarkParser,
5
+ createBlockTransformer,
6
+ defaultPlugins
5
7
  } from "@incremark/core";
6
8
  function useIncremark(options = {}) {
7
9
  const parserRef = useRef(null);
10
+ const transformerRef = useRef(null);
11
+ const hasTypewriterConfig = !!options.typewriter;
12
+ const cursorRef = useRef(options.typewriter?.cursor ?? "|");
8
13
  if (!parserRef.current) {
9
14
  parserRef.current = createIncremarkParser(options);
10
15
  }
16
+ if (hasTypewriterConfig && !transformerRef.current) {
17
+ const twOptions = options.typewriter;
18
+ transformerRef.current = createBlockTransformer({
19
+ charsPerTick: twOptions.charsPerTick ?? [1, 3],
20
+ tickInterval: twOptions.tickInterval ?? 30,
21
+ effect: twOptions.effect ?? "none",
22
+ pauseOnHidden: twOptions.pauseOnHidden ?? true,
23
+ plugins: twOptions.plugins ?? defaultPlugins,
24
+ onChange: () => {
25
+ setForceUpdateCount((c) => c + 1);
26
+ }
27
+ });
28
+ }
11
29
  const parser = parserRef.current;
30
+ const transformer = transformerRef.current;
12
31
  const [markdown, setMarkdown] = useState("");
13
32
  const [completedBlocks, setCompletedBlocks] = useState([]);
14
33
  const [pendingBlocks, setPendingBlocks] = useState([]);
15
34
  const [isLoading, setIsLoading] = useState(false);
16
- const blocks = useMemo(() => {
17
- const result = [];
18
- for (const block of completedBlocks) {
19
- result.push({ ...block, stableId: block.id });
35
+ const [forceUpdateCount, setForceUpdateCount] = useState(0);
36
+ const [typewriterEnabled, setTypewriterEnabled] = useState(options.typewriter?.enabled ?? hasTypewriterConfig);
37
+ const [isTypewriterProcessing, setIsTypewriterProcessing] = useState(false);
38
+ const [isTypewriterPaused, setIsTypewriterPaused] = useState(false);
39
+ const [typewriterEffect, setTypewriterEffect] = useState(
40
+ options.typewriter?.effect ?? "none"
41
+ );
42
+ const sourceBlocks = useMemo(
43
+ () => completedBlocks.map((block) => ({
44
+ id: block.id,
45
+ node: block.node,
46
+ status: block.status
47
+ })),
48
+ [completedBlocks]
49
+ );
50
+ useEffect(() => {
51
+ if (!transformer) return;
52
+ transformer.push(sourceBlocks);
53
+ const displayBlocks = transformer.getDisplayBlocks();
54
+ const currentDisplaying = displayBlocks.find((b) => !b.isDisplayComplete);
55
+ if (currentDisplaying) {
56
+ const updated = sourceBlocks.find((b) => b.id === currentDisplaying.id);
57
+ if (updated) {
58
+ transformer.update(updated);
59
+ }
20
60
  }
21
- for (let i = 0; i < pendingBlocks.length; i++) {
22
- result.push({
23
- ...pendingBlocks[i],
24
- stableId: `pending-${i}`
25
- });
61
+ setIsTypewriterProcessing(transformer.isProcessing());
62
+ setIsTypewriterPaused(transformer.isPausedState());
63
+ }, [sourceBlocks, transformer]);
64
+ const addCursorToNode = useCallback((node, cursor) => {
65
+ const cloned = JSON.parse(JSON.stringify(node));
66
+ function addToLast(n) {
67
+ if (n.children && n.children.length > 0) {
68
+ for (let i = n.children.length - 1; i >= 0; i--) {
69
+ if (addToLast(n.children[i])) {
70
+ return true;
71
+ }
72
+ }
73
+ n.children.push({ type: "text", value: cursor });
74
+ return true;
75
+ }
76
+ if (n.type === "text" && typeof n.value === "string") {
77
+ n.value += cursor;
78
+ return true;
79
+ }
80
+ if (typeof n.value === "string") {
81
+ n.value += cursor;
82
+ return true;
83
+ }
84
+ return false;
26
85
  }
27
- return result;
28
- }, [completedBlocks, pendingBlocks]);
86
+ addToLast(cloned);
87
+ return cloned;
88
+ }, []);
89
+ const blocks = useMemo(() => {
90
+ if (!typewriterEnabled || !transformer) {
91
+ const result = [];
92
+ for (const block of completedBlocks) {
93
+ result.push({ ...block, stableId: block.id });
94
+ }
95
+ for (let i = 0; i < pendingBlocks.length; i++) {
96
+ result.push({
97
+ ...pendingBlocks[i],
98
+ stableId: `pending-${i}`
99
+ });
100
+ }
101
+ return result;
102
+ }
103
+ const displayBlocks = transformer.getDisplayBlocks();
104
+ return displayBlocks.map((db, index) => {
105
+ const isPending = !db.isDisplayComplete;
106
+ const isLastPending = isPending && index === displayBlocks.length - 1;
107
+ let node = db.displayNode;
108
+ if (typewriterEffect === "typing" && isLastPending) {
109
+ node = addCursorToNode(db.displayNode, cursorRef.current);
110
+ }
111
+ return {
112
+ id: db.id,
113
+ stableId: db.id,
114
+ status: db.isDisplayComplete ? "completed" : "pending",
115
+ isLastPending,
116
+ node,
117
+ startOffset: 0,
118
+ endOffset: 0,
119
+ rawText: ""
120
+ };
121
+ });
122
+ }, [completedBlocks, pendingBlocks, typewriterEnabled, typewriterEffect, addCursorToNode, forceUpdateCount]);
29
123
  const ast = useMemo(
30
124
  () => ({
31
125
  type: "root",
@@ -65,7 +159,8 @@ function useIncremark(options = {}) {
65
159
  setPendingBlocks([]);
66
160
  setMarkdown("");
67
161
  setIsLoading(false);
68
- }, [parser]);
162
+ transformer?.reset();
163
+ }, [parser, transformer]);
69
164
  const render = useCallback(
70
165
  (content) => {
71
166
  const update = parser.render(content);
@@ -77,6 +172,59 @@ function useIncremark(options = {}) {
77
172
  },
78
173
  [parser]
79
174
  );
175
+ const skip = useCallback(() => {
176
+ transformer?.skip();
177
+ setIsTypewriterProcessing(false);
178
+ }, [transformer]);
179
+ const pause = useCallback(() => {
180
+ transformer?.pause();
181
+ setIsTypewriterPaused(true);
182
+ }, [transformer]);
183
+ const resume = useCallback(() => {
184
+ transformer?.resume();
185
+ setIsTypewriterPaused(false);
186
+ }, [transformer]);
187
+ const setTypewriterOptions = useCallback(
188
+ (opts) => {
189
+ if (opts.enabled !== void 0) {
190
+ setTypewriterEnabled(opts.enabled);
191
+ }
192
+ if (opts.charsPerTick !== void 0 || opts.tickInterval !== void 0 || opts.effect !== void 0 || opts.pauseOnHidden !== void 0) {
193
+ transformer?.setOptions({
194
+ charsPerTick: opts.charsPerTick,
195
+ tickInterval: opts.tickInterval,
196
+ effect: opts.effect,
197
+ pauseOnHidden: opts.pauseOnHidden
198
+ });
199
+ }
200
+ if (opts.effect !== void 0) {
201
+ setTypewriterEffect(opts.effect);
202
+ }
203
+ if (opts.cursor !== void 0) {
204
+ cursorRef.current = opts.cursor;
205
+ }
206
+ },
207
+ [transformer]
208
+ );
209
+ const typewriter = useMemo(
210
+ () => ({
211
+ enabled: typewriterEnabled,
212
+ setEnabled: setTypewriterEnabled,
213
+ isProcessing: isTypewriterProcessing,
214
+ isPaused: isTypewriterPaused,
215
+ effect: typewriterEffect,
216
+ skip,
217
+ pause,
218
+ resume,
219
+ setOptions: setTypewriterOptions
220
+ }),
221
+ [typewriterEnabled, isTypewriterProcessing, isTypewriterPaused, typewriterEffect, skip, pause, resume, setTypewriterOptions]
222
+ );
223
+ useEffect(() => {
224
+ return () => {
225
+ transformer?.destroy();
226
+ };
227
+ }, [transformer]);
80
228
  return {
81
229
  /** 已收集的完整 Markdown 字符串 */
82
230
  markdown,
@@ -86,7 +234,7 @@ function useIncremark(options = {}) {
86
234
  pendingBlocks,
87
235
  /** 当前完整的 AST */
88
236
  ast,
89
- /** 所有块(完成 + 待处理),带稳定 ID */
237
+ /** 用于渲染的 blocks(根据打字机设置自动处理) */
90
238
  blocks,
91
239
  /** 是否正在加载 */
92
240
  isLoading,
@@ -96,22 +244,24 @@ function useIncremark(options = {}) {
96
244
  finalize,
97
245
  /** 强制中断 */
98
246
  abort,
99
- /** 重置解析器 */
247
+ /** 重置解析器和打字机 */
100
248
  reset,
101
249
  /** 一次性渲染(reset + append + finalize) */
102
250
  render,
103
251
  /** 解析器实例 */
104
- parser
252
+ parser,
253
+ /** 打字机控制 */
254
+ typewriter
105
255
  };
106
256
  }
107
257
 
108
258
  // src/hooks/useDevTools.ts
109
- import { useEffect, useRef as useRef2 } from "react";
259
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
110
260
  import { createDevTools } from "@incremark/devtools";
111
261
  function useDevTools(incremark, options = {}) {
112
262
  const devtoolsRef = useRef2(null);
113
263
  const optionsRef = useRef2(options);
114
- useEffect(() => {
264
+ useEffect2(() => {
115
265
  const devtools = createDevTools(optionsRef.current);
116
266
  devtoolsRef.current = devtools;
117
267
  incremark.parser.setOnChange((state) => {
@@ -138,9 +288,9 @@ function useDevTools(incremark, options = {}) {
138
288
  }
139
289
 
140
290
  // src/hooks/useBlockTransformer.ts
141
- import { useState as useState2, useCallback as useCallback2, useRef as useRef3, useEffect as useEffect2 } from "react";
291
+ import { useState as useState2, useCallback as useCallback2, useRef as useRef3, useEffect as useEffect3 } from "react";
142
292
  import {
143
- createBlockTransformer
293
+ createBlockTransformer as createBlockTransformer2
144
294
  } from "@incremark/core";
145
295
  function useBlockTransformer(sourceBlocks, options = {}) {
146
296
  const [displayBlocks, setDisplayBlocks] = useState2([]);
@@ -149,7 +299,7 @@ function useBlockTransformer(sourceBlocks, options = {}) {
149
299
  const [effect, setEffect] = useState2(options.effect ?? "none");
150
300
  const transformerRef = useRef3(null);
151
301
  if (!transformerRef.current) {
152
- transformerRef.current = createBlockTransformer({
302
+ transformerRef.current = createBlockTransformer2({
153
303
  ...options,
154
304
  onChange: (blocks) => {
155
305
  setDisplayBlocks(blocks);
@@ -159,7 +309,7 @@ function useBlockTransformer(sourceBlocks, options = {}) {
159
309
  });
160
310
  }
161
311
  const transformer = transformerRef.current;
162
- useEffect2(() => {
312
+ useEffect3(() => {
163
313
  transformer.push(sourceBlocks);
164
314
  const currentDisplaying = displayBlocks.find((b) => !b.isDisplayComplete);
165
315
  if (currentDisplaying) {
@@ -169,7 +319,7 @@ function useBlockTransformer(sourceBlocks, options = {}) {
169
319
  }
170
320
  }
171
321
  }, [sourceBlocks, transformer]);
172
- useEffect2(() => {
322
+ useEffect3(() => {
173
323
  return () => {
174
324
  transformer.destroy();
175
325
  };
@@ -214,12 +364,26 @@ function useBlockTransformer(sourceBlocks, options = {}) {
214
364
  // src/components/IncremarkRenderer.tsx
215
365
  import React from "react";
216
366
  import { jsx, jsxs } from "react/jsx-runtime";
367
+ function getStableText(node) {
368
+ if (!node.chunks || node.chunks.length === 0) {
369
+ return node.value;
370
+ }
371
+ return node.value.slice(0, node.stableLength ?? 0);
372
+ }
217
373
  function renderInlineChildren(children) {
218
374
  if (!children) return null;
219
375
  return children.map((child, i) => {
220
376
  switch (child.type) {
221
- case "text":
222
- return /* @__PURE__ */ jsx(React.Fragment, { children: child.value }, i);
377
+ case "text": {
378
+ const textNode = child;
379
+ if (textNode.chunks && textNode.chunks.length > 0) {
380
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
381
+ getStableText(textNode),
382
+ textNode.chunks.map((chunk) => /* @__PURE__ */ jsx("span", { className: "incremark-fade-in", children: chunk.text }, chunk.createdAt))
383
+ ] }, i);
384
+ }
385
+ return /* @__PURE__ */ jsx(React.Fragment, { children: textNode.value }, i);
386
+ }
223
387
  case "strong":
224
388
  return /* @__PURE__ */ jsx("strong", { children: renderInlineChildren(child.children) }, i);
225
389
  case "emphasis":
@@ -236,6 +400,8 @@ function renderInlineChildren(children) {
236
400
  return /* @__PURE__ */ jsx("del", { children: renderInlineChildren(child.children) }, i);
237
401
  case "paragraph":
238
402
  return /* @__PURE__ */ jsx(React.Fragment, { children: renderInlineChildren(child.children) }, i);
403
+ case "html":
404
+ return /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: child.value } }, i);
239
405
  default:
240
406
  return /* @__PURE__ */ jsx("span", { children: child.value || "" }, i);
241
407
  }
@@ -254,7 +420,7 @@ var DefaultList = ({ node }) => {
254
420
  const Tag = node.ordered ? "ol" : "ul";
255
421
  return /* @__PURE__ */ jsx(Tag, { className: "incremark-list", children: node.children?.map((item, i) => /* @__PURE__ */ jsx("li", { children: renderInlineChildren(item.children) }, i)) });
256
422
  };
257
- var DefaultBlockquote = ({ node }) => /* @__PURE__ */ jsx("blockquote", { className: "incremark-blockquote", children: node.children?.map((child, i) => /* @__PURE__ */ jsx(React.Fragment, { children: child.type === "paragraph" ? /* @__PURE__ */ jsx("p", { children: renderInlineChildren(child.children) }) : renderInlineChildren(child.children || []) }, i)) });
423
+ var DefaultBlockquote = ({ node }) => /* @__PURE__ */ jsx("blockquote", { className: "incremark-blockquote", children: node.children?.map((child, i) => /* @__PURE__ */ jsx(React.Fragment, { children: child.type === "paragraph" ? /* @__PURE__ */ jsx("p", { children: renderInlineChildren(child.children) }) : "children" in child && Array.isArray(child.children) ? renderInlineChildren(child.children) : null }, i)) });
258
424
  var DefaultTable = ({ node }) => /* @__PURE__ */ jsx("div", { className: "incremark-table-wrapper", children: /* @__PURE__ */ jsxs("table", { className: "incremark-table", children: [
259
425
  /* @__PURE__ */ jsx("thead", { children: node.children?.[0] && /* @__PURE__ */ jsx("tr", { children: node.children[0].children?.map((cell, i) => /* @__PURE__ */ jsx("th", { children: renderInlineChildren(cell.children) }, i)) }) }),
260
426
  /* @__PURE__ */ jsx("tbody", { children: node.children?.slice(1).map((row, i) => /* @__PURE__ */ jsx("tr", { children: row.children?.map((cell, j) => /* @__PURE__ */ jsx("td", { children: renderInlineChildren(cell.children) }, j)) }, i)) })
@@ -298,7 +464,7 @@ var Incremark = ({
298
464
  // src/components/AutoScrollContainer.tsx
299
465
  import {
300
466
  useRef as useRef4,
301
- useEffect as useEffect3,
467
+ useEffect as useEffect4,
302
468
  useCallback as useCallback3,
303
469
  useState as useState3,
304
470
  forwardRef,
@@ -363,14 +529,14 @@ var AutoScrollContainer = forwardRef(
363
529
  lastScrollTopRef.current = scrollTop;
364
530
  lastScrollHeightRef.current = scrollHeight;
365
531
  }, [isNearBottom]);
366
- useEffect3(() => {
532
+ useEffect4(() => {
367
533
  const container = containerRef.current;
368
534
  if (container) {
369
535
  lastScrollTopRef.current = container.scrollTop;
370
536
  lastScrollHeightRef.current = container.scrollHeight;
371
537
  }
372
538
  }, []);
373
- useEffect3(() => {
539
+ useEffect4(() => {
374
540
  const container = containerRef.current;
375
541
  if (!container || !enabled) return;
376
542
  const observer = new MutationObserver(() => {
@@ -423,7 +589,7 @@ AutoScrollContainer.displayName = "AutoScrollContainer";
423
589
  // src/index.ts
424
590
  import {
425
591
  BlockTransformer as BlockTransformer2,
426
- createBlockTransformer as createBlockTransformer2,
592
+ createBlockTransformer as createBlockTransformer3,
427
593
  countChars,
428
594
  sliceAst,
429
595
  cloneNode,
@@ -432,7 +598,7 @@ import {
432
598
  imagePlugin,
433
599
  mathPlugin,
434
600
  thematicBreakPlugin,
435
- defaultPlugins,
601
+ defaultPlugins as defaultPlugins2,
436
602
  allPlugins,
437
603
  createPlugin
438
604
  } from "@incremark/core";
@@ -445,9 +611,9 @@ export {
445
611
  cloneNode,
446
612
  codeBlockPlugin,
447
613
  countChars,
448
- createBlockTransformer2 as createBlockTransformer,
614
+ createBlockTransformer3 as createBlockTransformer,
449
615
  createPlugin,
450
- defaultPlugins,
616
+ defaultPlugins2 as defaultPlugins,
451
617
  imagePlugin,
452
618
  mathPlugin,
453
619
  mermaidPlugin,
package/dist/styles.css CHANGED
@@ -189,3 +189,18 @@
189
189
  font-size: 11px;
190
190
  }
191
191
 
192
+ /* ============ 渐入动画效果 ============ */
193
+
194
+ .incremark-fade-in {
195
+ animation: incremark-fade-in 0.4s ease-out;
196
+ }
197
+
198
+ @keyframes incremark-fade-in {
199
+ from {
200
+ opacity: 0;
201
+ }
202
+ to {
203
+ opacity: 1;
204
+ }
205
+ }
206
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@incremark/react",
3
- "version": "0.0.5",
3
+ "version": "0.1.2",
4
4
  "license": "MIT",
5
5
  "description": "Incremark React integration - Incremental Markdown parser for AI streaming",
6
6
  "type": "module",
@@ -19,12 +19,13 @@
19
19
  ],
20
20
  "peerDependencies": {
21
21
  "react": ">=18.0.0",
22
- "@incremark/core": "0.0.5"
22
+ "@incremark/core": "0.1.2"
23
23
  },
24
24
  "dependencies": {
25
- "@incremark/devtools": "0.0.5"
25
+ "@incremark/devtools": "0.1.2"
26
26
  },
27
27
  "devDependencies": {
28
+ "@types/mdast": "^4.0.0",
28
29
  "@types/react": "^18.2.0",
29
30
  "react": "^18.2.0",
30
31
  "tsup": "^8.0.0",
@@ -35,7 +36,7 @@
35
36
  "url": "https://github.com/kingshuaishuai/incremark.git",
36
37
  "directory": "packages/react"
37
38
  },
38
- "homepage": "https://incremark-docs.vercel.app/",
39
+ "homepage": "https://www.incremark.com/",
39
40
  "scripts": {
40
41
  "build": "tsup && cp src/styles.css dist/styles.css",
41
42
  "dev": "tsup --watch"