forked from jstejada/react-typist
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTypist.jsx
116 lines (100 loc) · 2.68 KB
/
Typist.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import React, {Component, PropTypes} from 'react';
import Cursor from './Cursor';
import * as utils from './utils';
export default class Typist extends Component {
static propTypes = {
children: PropTypes.node,
className: PropTypes.string,
avgTypingDelay: PropTypes.number,
stdTypingDelay: PropTypes.number,
startDelay: PropTypes.number,
cursor: PropTypes.object,
onTypingDone: PropTypes.func,
delayGenerator: PropTypes.func,
}
static defaultProps = {
className: '',
avgTypingDelay: 70,
stdTypingDelay: 25,
startDelay: 0,
cursor: {},
onTypingDone: () => {},
delayGenerator: utils.gaussianRnd,
}
constructor(props) {
super(props);
if (this.props.children) {
this.toType = utils.extractText(this.props.children);
if (this.props.startDelay > 0) {
this.typeAll = setTimeout.bind(window, this.typeAll.bind(this), this.props.startDelay);
}
}
}
state = {
text: [],
isDone: false,
}
componentDidMount() {
if (this.props.children) {
this.typeAll();
} else {
this.onTypingDone();
}
}
shouldComponentUpdate(nextProps, nextState) {
for (let idx = 0; idx < nextState.text.length; idx++) {
const txt = this.state.text[idx];
const ntxt = nextState.text[idx];
if (txt !== ntxt && ntxt.length > 0) return true;
}
return this.state.isDone !== nextState.isDone;
}
onTypingDone = ()=> {
this.setState({isDone: true});
this.props.onTypingDone();
}
delayGenerator = (line, lineIdx, character, charIdx)=> {
const mean = this.props.avgTypingDelay;
const std = this.props.stdTypingDelay;
return this.props.delayGenerator(
mean,
std,
{
line,
lineIdx,
character,
charIdx,
defDelayGenerator: (mn = mean, st = std)=> utils.gaussianRnd(mn, st),
}
);
}
typeAll(strs = this.toType) {
utils.asyncEach(strs, (line, adv, idx)=> {
this.setState({text: this.state.text.concat([''])}, ()=> {
this.typeStr(line, idx, adv);
});
}, this.onTypingDone);
}
typeStr(line, idx, onDone = ()=>{}) {
utils.eachRndTimeout(
line,
(ch, adv)=> {
const text = this.state.text.slice();
text[idx] += ch;
this.setState({text}, adv);
},
onDone,
this.delayGenerator.bind(this, line, idx)
);
}
render() {
const className = this.props.className;
const innerTree = utils.extractTreeWithText(this.props.children, this.state.text);
return (
<div className={`Typist ${className}`}>
{innerTree}
<Cursor isDone={this.state.isDone} {...this.props.cursor} />
</div>
);
}
}