ds-markdown 0.1.2-beta.2 → 0.1.2-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -194,28 +194,43 @@ Let's explore these new features together!`);
194
194
  import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
195
195
  ```
196
196
 
197
- | Property | Type | Description | Default |
198
- | --------------- | --------------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------- |
199
- | `interval` | `number` | Typing interval (milliseconds) | `30` |
200
- | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | Timer type | Current default is `setTimeout`, will change to `requestAnimationFrame` later |
201
- | `answerType` | `'thinking'` \| `'answer'` | Content type (affects styling) | `'answer'` |
202
- | `theme` | `'light'` \| `'dark'` | Theme type | `'light'` |
203
- | `plugins` | `IMarkdownPlugin[]` | Plugin configuration | `[]` |
204
- | `math` | [IMarkdownMath](#IMarkdownMath) | Mathematical formula config | `{ splitSymbol: 'dollar' }` |
205
- | `onEnd` | `(data: EndData) => void` | Typing completion callback | - |
206
- | `onStart` | `(data: StartData) => void` | Typing start callback | - |
207
- | `onTypedChar` | `(data: `[ITypedChar](#ITypedChar)`) => void` | Character-by-character callback | - |
208
- | `disableTyping` | `boolean` | Disable typing animation | `false` |
197
+ | Property | Type | Description | Default |
198
+ | ------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
199
+ | `interval` | `number` | Typing interval (milliseconds) | `30` |
200
+ | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | Timer type | Current default is `setTimeout`, will change to `requestAnimationFrame` later |
201
+ | `answerType` | `'thinking'` \| `'answer'` | Content type (affects styling) | `'answer'` |
202
+ | `theme` | `'light'` \| `'dark'` | Theme type | `'light'` |
203
+ | `plugins` | `IMarkdownPlugin[]` | Plugin configuration | `[]` |
204
+ | `math` | [IMarkdownMath](#IMarkdownMath) | Mathematical formula config | `{ splitSymbol: 'dollar' }` |
205
+ | `onEnd` | `(data: EndData) => void` | Typing completion callback | - |
206
+ | `onStart` | `(data: StartData) => void` | Typing start callback | - |
207
+ | `onBeforeTypedChar` | `(data: IBeforeTypedChar) => Promise<void>` | Character typing pre-callback, supports async operations, blocks subsequent typing | - |
208
+ | `onTypedChar` | `(data: ITypedChar) => void` | Character typing post-callback | - |
209
+ | `disableTyping` | `boolean` | Disable typing animation | `false` |
210
+ | `autoStartTyping` | `boolean` | Whether to auto-start typing animation, set to false for manual trigger | `true` |
209
211
 
210
212
  > Note: If `disableTyping` changes from `true` to `false` during typing, all remaining characters will be displayed at once on the next typing trigger.
211
213
 
214
+ ### IBeforeTypedChar
215
+
216
+ | Property | Type | Description | Default |
217
+ | -------------- | ------------ | -------------------------------------------- | ------- |
218
+ | `currentIndex` | `number` | Current character index in the entire string | `0` |
219
+ | `currentChar` | `string` | Character about to be typed | - |
220
+ | `answerType` | `AnswerType` | Content type (thinking/answer) | - |
221
+ | `prevStr` | `string` | Previous string of current type content | - |
222
+ | `percent` | `number` | Typing progress percentage (0-100) | `0` |
223
+
212
224
  ### ITypedChar
213
225
 
214
- | Property | Type | Description | Default |
215
- | -------------- | -------- | ---------------------------------- | ------- |
216
- | `percent` | `number` | Typing progress percentage | `0` |
217
- | `currentChar` | `string` | Current character being typed | - |
218
- | `currentIndex` | `number` | Current index in the entire string | `0` |
226
+ | Property | Type | Description | Default |
227
+ | -------------- | ------------ | -------------------------------------------- | ------- |
228
+ | `currentIndex` | `number` | Current character index in the entire string | `0` |
229
+ | `currentChar` | `string` | Character that was just typed | - |
230
+ | `answerType` | `AnswerType` | Content type (thinking/answer) | - |
231
+ | `prevStr` | `string` | Previous string of current type content | - |
232
+ | `currentStr` | `string` | Complete string of current type content | - |
233
+ | `percent` | `number` | Typing progress percentage (0-100) | `0` |
219
234
 
220
235
  #### IMarkdownMath
221
236
 
@@ -241,26 +256,32 @@ import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
241
256
 
242
257
  #### Default export DsMarkdown
243
258
 
244
- | Method | Parameters | Description |
245
- | -------- | ---------- | ------------- |
246
- | `stop` | - | Pause typing |
247
- | `resume` | - | Resume typing |
259
+ | Method | Parameters | Description |
260
+ | --------- | ---------- | ------------------------------------------------------------- |
261
+ | `start` | - | Start typing animation |
262
+ | `stop` | - | Pause typing |
263
+ | `resume` | - | Resume typing |
264
+ | `restart` | - | Restart typing animation, play current content from beginning |
248
265
 
249
266
  #### MarkdownCMD Exposed Methods
250
267
 
251
- | Method | Parameters | Description |
252
- | ----------------- | ------------------------------------------- | ----------------------------- |
253
- | `push` | `(content: string, answerType: AnswerType)` | Add content and start typing |
254
- | `clear` | - | Clear all content and state |
255
- | `triggerWholeEnd` | - | Manually trigger end callback |
256
- | `stop` | - | Pause typing |
257
- | `resume` | - | Resume typing |
268
+ | Method | Parameters | Description |
269
+ | ----------------- | ------------------------------------------- | ------------------------------------------------------------- |
270
+ | `push` | `(content: string, answerType: AnswerType)` | Add content and start typing |
271
+ | `clear` | - | Clear all content and state |
272
+ | `triggerWholeEnd` | - | Manually trigger end callback |
273
+ | `start` | - | Start typing animation |
274
+ | `stop` | - | Pause typing |
275
+ | `resume` | - | Resume typing |
276
+ | `restart` | - | Restart typing animation, play current content from beginning |
258
277
 
259
278
  **Usage example:**
260
279
 
261
280
  ```tsx
281
+ markdownRef.current?.start(); // Start animation
262
282
  markdownRef.current?.stop(); // Pause animation
263
283
  markdownRef.current?.resume(); // Resume animation
284
+ markdownRef.current?.restart(); // Restart animation
264
285
  ```
265
286
 
266
287
  ---
@@ -533,6 +554,211 @@ function MathStreamingDemo() {
533
554
  }
534
555
  ```
535
556
 
557
+ ### 🎯 Advanced Callback Control
558
+
559
+ ```tsx
560
+ import { useRef, useState } from 'react';
561
+ import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
562
+
563
+ function AdvancedCallbackDemo() {
564
+ const markdownRef = useRef<MarkdownCMDRef>(null);
565
+ const [typingStats, setTypingStats] = useState({ progress: 0, currentChar: '', totalChars: 0 });
566
+
567
+ const handleBeforeTypedChar = async (data) => {
568
+ // Perform async operations before character typing
569
+ console.log('About to type:', data.currentChar);
570
+
571
+ // Can perform network requests, data validation, etc.
572
+ if (data.currentChar === '!') {
573
+ await new Promise((resolve) => setTimeout(resolve, 500)); // Simulate delay
574
+ }
575
+ };
576
+
577
+ const handleTypedChar = (data) => {
578
+ // Update typing statistics
579
+ setTypingStats({
580
+ progress: Math.round(data.percent),
581
+ currentChar: data.currentChar,
582
+ totalChars: data.currentIndex + 1,
583
+ });
584
+
585
+ // Can add sound effects, animations, etc.
586
+ if (data.currentChar === '.') {
587
+ // Play period sound effect
588
+ console.log('Play period sound effect');
589
+ }
590
+ };
591
+
592
+ const handleStart = (data) => {
593
+ console.log('Start typing:', data.currentChar);
594
+ };
595
+
596
+ const handleEnd = (data) => {
597
+ console.log('Typing complete:', data.str);
598
+ };
599
+
600
+ const startDemo = () => {
601
+ markdownRef.current?.clear();
602
+ markdownRef.current?.push(
603
+ '# Advanced Callback Demo\n\n' +
604
+ 'This example shows how to use `onBeforeTypedChar` and `onTypedChar` callbacks:\n\n' +
605
+ '- 🎯 **Pre-typing callback**: Can perform async operations before character display\n' +
606
+ '- 📊 **Post-typing callback**: Can update progress in real-time and add effects\n' +
607
+ '- ⚡ **Performance optimization**: Supports async operations without affecting typing smoothness\n\n' +
608
+ 'Current progress: ' +
609
+ typingStats.progress +
610
+ '%\n' +
611
+ 'Characters typed: ' +
612
+ typingStats.totalChars +
613
+ '\n\n' +
614
+ 'This is a very powerful feature!',
615
+ 'answer',
616
+ );
617
+ };
618
+
619
+ return (
620
+ <div>
621
+ <button onClick={startDemo}>🚀 Start Advanced Demo</button>
622
+
623
+ <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
624
+ <strong>Typing Stats:</strong> Progress {typingStats.progress}% | Current char: "{typingStats.currentChar}" | Total chars: {typingStats.totalChars}
625
+ </div>
626
+
627
+ <MarkdownCMD ref={markdownRef} interval={30} onBeforeTypedChar={handleBeforeTypedChar} onTypedChar={handleTypedChar} onStart={handleStart} onEnd={handleEnd} />
628
+ </div>
629
+ );
630
+ }
631
+ ```
632
+
633
+ ### 🔄 Restart Animation Demo
634
+
635
+ ```tsx
636
+ import { useRef, useState } from 'react';
637
+ import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
638
+
639
+ function RestartDemo() {
640
+ const markdownRef = useRef<MarkdownCMDRef>(null);
641
+ const [isPlaying, setIsPlaying] = useState(false);
642
+
643
+ const startContent = () => {
644
+ markdownRef.current?.clear();
645
+ markdownRef.current?.push(
646
+ '# Restart Animation Demo\n\n' +
647
+ 'This example shows how to use the `restart()` method:\n\n' +
648
+ '- 🔄 **Restart**: Play current content from the beginning\n' +
649
+ '- ⏸️ **Pause/Resume**: Can pause and resume at any time\n' +
650
+ '- 🎯 **Precise Control**: Complete control over animation playback state\n\n' +
651
+ 'Current state: ' +
652
+ (isPlaying ? 'Playing' : 'Paused') +
653
+ '\n\n' +
654
+ 'This is a very practical feature!',
655
+ 'answer',
656
+ );
657
+ setIsPlaying(true);
658
+ };
659
+
660
+ const handleStart = () => {
661
+ markdownRef.current?.start();
662
+ setIsPlaying(true);
663
+ };
664
+
665
+ const handleStop = () => {
666
+ markdownRef.current?.stop();
667
+ setIsPlaying(false);
668
+ };
669
+
670
+ const handleResume = () => {
671
+ markdownRef.current?.resume();
672
+ setIsPlaying(true);
673
+ };
674
+
675
+ const handleRestart = () => {
676
+ markdownRef.current?.restart();
677
+ setIsPlaying(true);
678
+ };
679
+
680
+ const handleEnd = () => {
681
+ setIsPlaying(false);
682
+ };
683
+
684
+ return (
685
+ <div>
686
+ <div style={{ marginBottom: '10px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
687
+ <button onClick={startContent}>🚀 Start Content</button>
688
+ <button onClick={handleStart} disabled={isPlaying}>
689
+ ▶️ Start
690
+ </button>
691
+ <button onClick={handleStop} disabled={!isPlaying}>
692
+ ⏸️ Pause
693
+ </button>
694
+ <button onClick={handleResume} disabled={isPlaying}>
695
+ ▶️ Resume
696
+ </button>
697
+ <button onClick={handleRestart}>🔄 Restart</button>
698
+ </div>
699
+
700
+ <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
701
+ <strong>Animation State:</strong> {isPlaying ? '🟢 Playing' : '🔴 Paused'}
702
+ </div>
703
+
704
+ <MarkdownCMD ref={markdownRef} interval={25} onEnd={handleEnd} />
705
+ </div>
706
+ );
707
+ }
708
+ ```
709
+
710
+ ### ▶️ Manual Start Animation Demo
711
+
712
+ ```tsx
713
+ import { useRef, useState } from 'react';
714
+ import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
715
+
716
+ function StartDemo() {
717
+ const markdownRef = useRef<MarkdownCMDRef>(null);
718
+ const [isPlaying, setIsPlaying] = useState(false);
719
+
720
+ const loadContent = () => {
721
+ markdownRef.current?.clear();
722
+ markdownRef.current?.push(
723
+ '# Manual Start Animation Demo\n\n' +
724
+ 'This example shows how to use the `start()` method:\n\n' +
725
+ '- 🎯 **Manual Control**: When `autoStartTyping=false`, need to manually call `start()`\n' +
726
+ '- ⏱️ **Delayed Start**: Can start animation after user interaction\n' +
727
+ '- 🎮 **Gamification**: Suitable for scenarios requiring user initiative\n\n' +
728
+ 'Click the "Start Animation" button to manually trigger the typing effect!',
729
+ 'answer',
730
+ );
731
+ setIsPlaying(false);
732
+ };
733
+
734
+ const handleStart = () => {
735
+ markdownRef.current?.start();
736
+ setIsPlaying(true);
737
+ };
738
+
739
+ const handleEnd = () => {
740
+ setIsPlaying(false);
741
+ };
742
+
743
+ return (
744
+ <div>
745
+ <div style={{ marginBottom: '10px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
746
+ <button onClick={loadContent}>📝 Load Content</button>
747
+ <button onClick={handleStart} disabled={isPlaying}>
748
+ ▶️ Start Animation
749
+ </button>
750
+ </div>
751
+
752
+ <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
753
+ <strong>State:</strong> {isPlaying ? '🟢 Animation Playing' : '🔴 Waiting to Start'}
754
+ </div>
755
+
756
+ <MarkdownCMD ref={markdownRef} interval={30} autoStartTyping={false} onEnd={handleEnd} />
757
+ </div>
758
+ );
759
+ }
760
+ ```
761
+
536
762
  ## 🔧 Best Practices
537
763
 
538
764
  ### 1. Performance Optimization
package/README.ja.md CHANGED
@@ -33,11 +33,6 @@
33
33
  - ライト/ダークテーマサポート、様々なプロダクトスタイルに対応
34
34
  - remark/rehype プラグイン拡張をサポートするプラグインアーキテクチャ
35
35
 
36
- ### �� **開発者エクスペリエンス**
37
-
38
- - タイピングの中断 `stop` と再開 `resume` をサポート
39
- - タイピングの無効化と有効化をサポート
40
-
41
36
  ### 🎬 **滑らかなアニメーション**
42
37
 
43
38
  - デュアルタイマーモード最適化、`requestAnimationFrame` と `setTimeout` モードをサポート
@@ -194,28 +189,43 @@ React 19 は多くのエキサイティングな新機能をもたらします
194
189
  import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
195
190
  ```
196
191
 
197
- | プロパティ | 型 | 説明 | デフォルト |
198
- | --------------- | --------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------- |
199
- | `interval` | `number` | タイピング間隔(ミリ秒) | `30` |
200
- | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | タイマータイプ | 現在のデフォルトは`setTimeout`、後で`requestAnimationFrame`に変更予定 |
201
- | `answerType` | `'thinking'` \| `'answer'` | コンテンツタイプ(スタイルに影響) | `'answer'` |
202
- | `theme` | `'light'` \| `'dark'` | テーマタイプ | `'light'` |
203
- | `plugins` | `IMarkdownPlugin[]` | プラグイン設定 | `[]` |
204
- | `math` | [IMarkdownMath](#IMarkdownMath) | 数式設定 | `{ splitSymbol: 'dollar' }` |
205
- | `onEnd` | `(data: EndData) => void` | タイピング完了コールバック | - |
206
- | `onStart` | `(data: StartData) => void` | タイピング開始コールバック | - |
207
- | `onTypedChar` | `(data: `[ITypedChar](#ITypedChar)`) => void` | 文字ごとのタイピングコールバック | - |
208
- | `disableTyping` | `boolean` | タイピングアニメーション効果を無効 | `false` |
192
+ | プロパティ | 型 | 説明 | デフォルト |
193
+ | ------------------- | ------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
194
+ | `interval` | `number` | タイピング間隔(ミリ秒) | `30` |
195
+ | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | タイマータイプ | 現在のデフォルトは`setTimeout`、後で`requestAnimationFrame`に変更予定 |
196
+ | `answerType` | `'thinking'` \| `'answer'` | コンテンツタイプ(スタイルに影響) | `'answer'` |
197
+ | `theme` | `'light'` \| `'dark'` | テーマタイプ | `'light'` |
198
+ | `plugins` | `IMarkdownPlugin[]` | プラグイン設定 | `[]` |
199
+ | `math` | [IMarkdownMath](#IMarkdownMath) | 数式設定 | `{ splitSymbol: 'dollar' }` |
200
+ | `onEnd` | `(data: EndData) => void` | タイピング完了コールバック | - |
201
+ | `onStart` | `(data: StartData) => void` | タイピング開始コールバック | - |
202
+ | `onBeforeTypedChar` | `(data: IBeforeTypedChar) => Promise<void>` | 文字タイピング前コールバック、非同期操作をサポート、後続のタイピングをブロック | - |
203
+ | `onTypedChar` | `(data: ITypedChar) => void` | 文字タイピング後コールバック | - |
204
+ | `disableTyping` | `boolean` | タイピングアニメーション効果を無効 | `false` |
205
+ | `autoStartTyping` | `boolean` | タイピングアニメーションを自動開始するかどうか、falseの場合は手動トリガー | `true` |
209
206
 
210
207
  > 注意: タイピング中に `disableTyping` が `true` から `false` に変わると、次のタイピングトリガー時に残りの全文字が一度に表示されます。
211
208
 
209
+ ### IBeforeTypedChar
210
+
211
+ | プロパティ | 型 | 説明 | デフォルト |
212
+ | -------------- | ------------ | ------------------------------------- | ---------- |
213
+ | `currentIndex` | `number` | 文字列全体での現在のインデックス | `0` |
214
+ | `currentChar` | `string` | タイピング予定の文字 | - |
215
+ | `answerType` | `AnswerType` | コンテンツタイプ(thinking/answer) | - |
216
+ | `prevStr` | `string` | 現在のタイプコンテンツの前の文字列 | - |
217
+ | `percent` | `number` | タイピング進行パーセンテージ(0-100) | `0` |
218
+
212
219
  ### ITypedChar
213
220
 
214
- | プロパティ | 型 | 説明 | デフォルト |
215
- | -------------- | -------- | -------------------------------- | ---------- |
216
- | `percent` | `number` | タイピング進行パーセンテージ | `0` |
217
- | `currentChar` | `string` | 現在タイピング中の文字 | - |
218
- | `currentIndex` | `number` | 文字列全体での現在のインデックス | `0` |
221
+ | プロパティ | 型 | 説明 | デフォルト |
222
+ | -------------- | ------------ | ------------------------------------- | ---------- |
223
+ | `currentIndex` | `number` | 文字列全体での現在のインデックス | `0` |
224
+ | `currentChar` | `string` | タイピング済みの文字 | - |
225
+ | `answerType` | `AnswerType` | コンテンツタイプ(thinking/answer) | - |
226
+ | `prevStr` | `string` | 現在のタイプコンテンツの前の文字列 | - |
227
+ | `currentStr` | `string` | 現在のタイプコンテンツの完全な文字列 | - |
228
+ | `percent` | `number` | タイピング進行パーセンテージ(0-100) | `0` |
219
229
 
220
230
  #### IMarkdownMath
221
231
 
@@ -241,26 +251,32 @@ import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
241
251
 
242
252
  #### デフォルトエクスポート DsMarkdown
243
253
 
244
- | メソッド | パラメータ | 説明 |
245
- | -------- | ---------- | -------------------- |
246
- | `stop` | - | タイピングを一時停止 |
247
- | `resume` | - | タイピングを再開 |
254
+ | メソッド | パラメータ | 説明 |
255
+ | --------- | ---------- | -------------------------------------------------------------- |
256
+ | `start` | - | タイピングアニメーションを開始 |
257
+ | `stop` | - | タイピングを一時停止 |
258
+ | `resume` | - | タイピングを再開 |
259
+ | `restart` | - | タイピングアニメーションを再開、現在のコンテンツを最初から再生 |
248
260
 
249
261
  #### MarkdownCMD 公開メソッド
250
262
 
251
- | メソッド | パラメータ | 説明 |
252
- | ----------------- | ------------------------------------------- | ---------------------------------- |
253
- | `push` | `(content: string, answerType: AnswerType)` | コンテンツを追加してタイピング開始 |
254
- | `clear` | - | 全コンテンツと状態をクリア |
255
- | `triggerWholeEnd` | - | 手動で完了コールバックを発火 |
256
- | `stop` | - | タイピングを一時停止 |
257
- | `resume` | - | タイピングを再開 |
263
+ | メソッド | パラメータ | 説明 |
264
+ | ----------------- | ------------------------------------------- | -------------------------------------------------------------- |
265
+ | `push` | `(content: string, answerType: AnswerType)` | コンテンツを追加してタイピング開始 |
266
+ | `clear` | - | 全コンテンツと状態をクリア |
267
+ | `triggerWholeEnd` | - | 手動で完了コールバックを発火 |
268
+ | `start` | - | タイピングアニメーションを開始 |
269
+ | `stop` | - | タイピングを一時停止 |
270
+ | `resume` | - | タイピングを再開 |
271
+ | `restart` | - | タイピングアニメーションを再開、現在のコンテンツを最初から再生 |
258
272
 
259
273
  **使用例:**
260
274
 
261
275
  ```tsx
276
+ markdownRef.current?.start(); // アニメーションを開始
262
277
  markdownRef.current?.stop(); // アニメーションを一時停止
263
278
  markdownRef.current?.resume(); // アニメーションを再開
279
+ markdownRef.current?.restart(); // アニメーションを再開
264
280
  ```
265
281
 
266
282
  ---
package/README.ko.md CHANGED
@@ -194,28 +194,43 @@ React 19는 많은 흥미로운 새 기능을 제공합니다:
194
194
  import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
195
195
  ```
196
196
 
197
- | 속성 | 타입 | 설명 | 기본값 |
198
- | --------------- | --------------------------------------------- | -------------------------- | ---------------------------------------------------------------------- |
199
- | `interval` | `number` | 타이핑 간격 (밀리초) | `30` |
200
- | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | 타이머 타입 | 현재 기본값은 `setTimeout`, 나중에 `requestAnimationFrame`로 변경 예정 |
201
- | `answerType` | `'thinking'` \| `'answer'` | 콘텐츠 타입 (스타일 영향) | `'answer'` |
202
- | `theme` | `'light'` \| `'dark'` | 테마 타입 | `'light'` |
203
- | `plugins` | `IMarkdownPlugin[]` | 플러그인 설정 | `[]` |
204
- | `math` | [IMarkdownMath](#IMarkdownMath) | 수학 공식 설정 | `{ splitSymbol: 'dollar' }` |
205
- | `onEnd` | `(data: EndData) => void` | 타이핑 완료 콜백 | - |
206
- | `onStart` | `(data: StartData) => void` | 타이핑 시작 콜백 | - |
207
- | `onTypedChar` | `(data: `[ITypedChar](#ITypedChar)`) => void` | 문자별 타이핑 콜백 | - |
208
- | `disableTyping` | `boolean` | 타이핑 애니메이션 비활성화 | `false` |
197
+ | 속성 | 타입 | 설명 | 기본값 |
198
+ | ------------------- | ------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------- |
199
+ | `interval` | `number` | 타이핑 간격 (밀리초) | `30` |
200
+ | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | 타이머 타입 | 현재 기본값은 `setTimeout`, 나중에 `requestAnimationFrame`로 변경 예정 |
201
+ | `answerType` | `'thinking'` \| `'answer'` | 콘텐츠 타입 (스타일 영향) | `'answer'` |
202
+ | `theme` | `'light'` \| `'dark'` | 테마 타입 | `'light'` |
203
+ | `plugins` | `IMarkdownPlugin[]` | 플러그인 설정 | `[]` |
204
+ | `math` | [IMarkdownMath](#IMarkdownMath) | 수학 공식 설정 | `{ splitSymbol: 'dollar' }` |
205
+ | `onEnd` | `(data: EndData) => void` | 타이핑 완료 콜백 | - |
206
+ | `onStart` | `(data: StartData) => void` | 타이핑 시작 콜백 | - |
207
+ | `onBeforeTypedChar` | `(data: IBeforeTypedChar) => Promise<void>` | 문자 타이핑 전 콜백, 비동기 작업 지원, 후속 타이핑 차단 | - |
208
+ | `onTypedChar` | `(data: ITypedChar) => void` | 문자 타이핑 콜백 | - |
209
+ | `disableTyping` | `boolean` | 타이핑 애니메이션 비활성화 | `false` |
210
+ | `autoStartTyping` | `boolean` | 타이핑 애니메이션 자동 시작 여부, false인 경우 수동 트리거 | `true` |
209
211
 
210
212
  > 참고: 타이핑 중에 `disableTyping`이 `true`에서 `false`로 변경되면 다음 타이핑 트리거 시 남은 모든 문자가 한 번에 표시됩니다.
211
213
 
214
+ ### IBeforeTypedChar
215
+
216
+ | 속성 | 타입 | 설명 | 기본값 |
217
+ | -------------- | ------------ | ------------------------------ | ------ |
218
+ | `currentIndex` | `number` | 전체 문자열에서 현재 인덱스 | `0` |
219
+ | `currentChar` | `string` | 타이핑 예정 문자 | - |
220
+ | `answerType` | `AnswerType` | 콘텐츠 타입 (thinking/answer) | - |
221
+ | `prevStr` | `string` | 현재 타입 콘텐츠의 이전 문자열 | - |
222
+ | `percent` | `number` | 타이핑 진행률 백분율 (0-100) | `0` |
223
+
212
224
  ### ITypedChar
213
225
 
214
- | 속성 | 타입 | 설명 | 기본값 |
215
- | -------------- | -------- | --------------------------- | ------ |
216
- | `percent` | `number` | 타이핑 진행률 백분율 | `0` |
217
- | `currentChar` | `string` | 현재 타이핑 중인 문자 | - |
218
- | `currentIndex` | `number` | 전체 문자열에서 현재 인덱스 | `0` |
226
+ | 속성 | 타입 | 설명 | 기본값 |
227
+ | -------------- | ------------ | -------------------------------- | ------ |
228
+ | `currentIndex` | `number` | 전체 문자열에서 현재 인덱스 | `0` |
229
+ | `currentChar` | `string` | 타이핑된 문자 | - |
230
+ | `answerType` | `AnswerType` | 콘텐츠 타입 (thinking/answer) | - |
231
+ | `prevStr` | `string` | 현재 타입 콘텐츠의 이전 문자열 | - |
232
+ | `currentStr` | `string` | 현재 타입 콘텐츠의 완전한 문자열 | - |
233
+ | `percent` | `number` | 타이핑 진행률 백분율 (0-100) | `0` |
219
234
 
220
235
  #### IMarkdownMath
221
236
 
@@ -241,26 +256,32 @@ import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
241
256
 
242
257
  #### 기본 내보내기 DsMarkdown
243
258
 
244
- | 메서드 | 매개변수 | 설명 |
245
- | -------- | -------- | --------------- |
246
- | `stop` | - | 타이핑 일시정지 |
247
- | `resume` | - | 타이핑 재개 |
259
+ | 메서드 | 매개변수 | 설명 |
260
+ | --------- | -------- | ----------------------------------------------------- |
261
+ | `start` | - | 타이핑 애니메이션 시작 |
262
+ | `stop` | - | 타이핑 일시정지 |
263
+ | `resume` | - | 타이핑 재개 |
264
+ | `restart` | - | 타이핑 애니메이션 재시작, 현재 콘텐츠를 처음부터 재생 |
248
265
 
249
266
  #### MarkdownCMD 노출 메서드
250
267
 
251
- | 메서드 | 매개변수 | 설명 |
252
- | ----------------- | ------------------------------------------- | -------------------------- |
253
- | `push` | `(content: string, answerType: AnswerType)` | 콘텐츠 추가 및 타이핑 시작 |
254
- | `clear` | - | 모든 콘텐츠 및 상태 지우기 |
255
- | `triggerWholeEnd` | - | 수동으로 완료 콜백 트리거 |
256
- | `stop` | - | 타이핑 일시정지 |
257
- | `resume` | - | 타이핑 재개 |
268
+ | 메서드 | 매개변수 | 설명 |
269
+ | ----------------- | ------------------------------------------- | ----------------------------------------------------- |
270
+ | `push` | `(content: string, answerType: AnswerType)` | 콘텐츠 추가 및 타이핑 시작 |
271
+ | `clear` | - | 모든 콘텐츠 및 상태 지우기 |
272
+ | `triggerWholeEnd` | - | 수동으로 완료 콜백 트리거 |
273
+ | `start` | - | 타이핑 애니메이션 시작 |
274
+ | `stop` | - | 타이핑 일시정지 |
275
+ | `resume` | - | 타이핑 재개 |
276
+ | `restart` | - | 타이핑 애니메이션 재시작, 현재 콘텐츠를 처음부터 재생 |
258
277
 
259
278
  **사용 예:**
260
279
 
261
280
  ```tsx
281
+ markdownRef.current?.start(); // 애니메이션 시작
262
282
  markdownRef.current?.stop(); // 애니메이션 일시정지
263
283
  markdownRef.current?.resume(); // 애니메이션 재개
284
+ markdownRef.current?.restart(); // 애니메이션 재시작
264
285
  ```
265
286
 
266
287
  ---