-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypewriter.js
80 lines (72 loc) · 1.26 KB
/
typewriter.js
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
import {
compose,
concat,
curry,
filter,
isEmpty,
join,
length,
map,
not,
nth,
reduce,
repeat,
replace,
split,
take,
takeWhile,
transpose,
trim
} from 'rambda'
const clear = compose(
reduce(
compose(
replace(/.?[\b]/, ''),
concat
),
''
),
split('')
)
const backspaces = compose(join(''), repeat('\b'))
const collisions = compose(
length,
takeWhile(v => nth(0, v) === nth(1, v)),
transpose,
map(split(''))
)
const diff = curry((replace, origin) => {
const c = collisions([replace, origin])
return backspaces(origin.length - c) + replace.slice(c)
})
const diffAll = compose(
join(''),
reduce((a, v) => [
...a,
compose(
diff(v),
clear,
join('')
)(a)
], [])
)
export default (node, { speed = 50, separator }) => {
const children = compose(
filter(compose(not, isEmpty)),
map(trim),
split(separator),
join(''),
map(({ textContent }) => textContent),
filter(({ nodeType }) => nodeType === Node.TEXT_NODE),
Array.from
)(node.childNodes)
const text = diffAll(children)
const duration = text.length * speed
return {
duration,
tick: t => {
const i = ~~(text.length * t)
node.textContent = clear(take(i, text))
}
}
}