Skip to content

Commit 2cce0c1

Browse files
committed
Update README.md with live demo link and enhance documentation for onCharacterAnimationComplete prop; increment version in package.json
1 parent b1604e5 commit 2cce0c1

File tree

4 files changed

+53
-27
lines changed

4 files changed

+53
-27
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
This library provides a new component, `MarkdownTypewriter`, that combines the Markdown component of [react-markdown](https://www.npmjs.com/package/react-markdown) with the animation of typewriter. The animation was created entirely with [motion](https://www.npmjs.com/package/motion).
44

5+
Live demo: https://codesandbox.io/p/sandbox/react-markdown-typewriter-rgjf6t
6+
57
## Why?
68

79
This library was born during the development of my game engine [pixi-vn](https://www.npmjs.com/package/@drincs/pixi-vn). I needed a component that would display the current dialogue of a character with the "Typewriter" effect and I also wanted to give the developer the possibility to use Markdown to add style to the text.
@@ -50,7 +52,6 @@ export default function NarrationScreen() {
5052
remarkPlugins={[remarkGfm]}
5153
rehypePlugins={[rehypeRaw]}
5254
delay={20}
53-
scrollRef={paragraphRef}
5455
motionProps={{
5556
onAnimationComplete: () => {
5657
console.log("Typewriter finished");
@@ -59,6 +60,15 @@ export default function NarrationScreen() {
5960
hidden: { opacity: 0 },
6061
visible: { opacity: 1, transition: { opacity: { duration: 0 } } },
6162
},
63+
onCharacterAnimationComplete: (ref) => {
64+
if (paragraphRef.current && ref.current) {
65+
let scrollTop = ref.current.offsetTop - paragraphRef.current.clientHeight / 2;
66+
paragraphRef.current.scrollTo({
67+
top: scrollTop,
68+
behavior: "auto",
69+
});
70+
}
71+
},
6272
}}
6373
>
6474
Hello World
@@ -75,7 +85,7 @@ export default function NarrationScreen() {
7585
In addition to the `react-markdown` component props, the component accepts the following props:
7686

7787
* `delay`: The delay in milliseconds between the appearance of one letter and the next. Default: `10`. (Optional)
78-
* `scrollRef`: The reference to the element that will be scrolled when the text exceeds the height of the container. (Optional)
7988
* `motionProps` (Optional):
8089
* The props to pass to the [motion span](https://motion.dev/docs/react-motion-component).
8190
* `characterVariants`: The motion variants for each individual letter. Default: `{ hidden: { opacity: 0 }, visible: { opacity: 1, transition: { opacity: { duration: 0 } } } }` (Optional).
91+
* `onCharacterAnimationComplete`: A callback that is called when the animation of a letter is complete. The callback is called with the reference to the letter. (Optional)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-markdown-typewriter",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "React Markdown component where Typewriter effect with motion has been added.",
55
"main": "./dist/index.cjs",
66
"module": "./dist/index.js",

src/components/MarkdownTypewriter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ export default function MarkdownTypewriter(
99
) {
1010
const {
1111
delay = 10,
12-
onCharacterAnimationComplete,
1312
children: text,
1413
motionProps = {},
1514
...rest
@@ -19,6 +18,7 @@ export default function MarkdownTypewriter(
1918
hidden: { opacity: 0 },
2019
visible: { opacity: 1, transition: { opacity: { duration: 0 } } },
2120
},
21+
onCharacterAnimationComplete,
2222
...restMotionProps
2323
} = motionProps;
2424
const sentenceVariants = useMemo<Variants>(

src/interfaces/MarkdownTypewriterProps.ts

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,44 @@ export default interface MarkdownTypewriterProps extends Omit<Options, "componen
2020
* @default { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { opacity: { duration: 0 } } } }
2121
*/
2222
characterVariants?: Variants;
23+
/**
24+
* A callback that is called when the animation of a letter is complete.
25+
* The callback is called with the reference to the letter.
26+
*
27+
* @example
28+
* ```tsx
29+
* import { useRef } from "react";
30+
*
31+
* export default function NarrationScreen() {
32+
* const paragraphRef = useRef<HTMLDivElement>(null);
33+
* return (
34+
* <div
35+
* ref={paragraphRef}
36+
* style={{
37+
* overflow: "auto",
38+
* height: "300px",
39+
* }}
40+
* >
41+
* <MarkdownTypewriter
42+
* motionProps={{
43+
* onCharacterAnimationComplete: (ref) => {
44+
* if (paragraphRef.current && ref.current) {
45+
* let scrollTop = ref.current.offsetTop - paragraphRef.current.clientHeight / 2;
46+
* paragraphRef.current.scrollTo({
47+
* top: scrollTop,
48+
* behavior: "auto",
49+
* });
50+
* }
51+
* }
52+
* }}
53+
* >
54+
* Hello World
55+
* </MarkdownTypewriter>
56+
* </div>
57+
* );
58+
* }
59+
* ```
60+
*/
61+
onCharacterAnimationComplete?: (letterRef: RefObject<HTMLSpanElement | null>) => void;
2362
};
24-
/**
25-
* The reference to the element that will be scrolled when the text exceeds the height of the container.
26-
*
27-
* @example
28-
* ```tsx
29-
* import { useRef } from "react";
30-
* import MarkdownTypewriter from "../components/Typewriter";
31-
*
32-
* export default function NarrationScreen() {
33-
* const paragraphRef = useRef<HTMLDivElement>(null);
34-
* return (
35-
* <div ref={paragraphRef}>
36-
* <MarkdownTypewriter
37-
* scrollRef={paragraphRef}
38-
* >
39-
* Hello World
40-
* </MarkdownTypewriter>
41-
* </div>
42-
* );
43-
* }
44-
* ```
45-
*/
46-
scrollRef?: RefObject<HTMLDivElement | null>;
4763
}

0 commit comments

Comments
 (0)