Skip to content

Instantly share code, notes, and snippets.

@zyxd
Created December 12, 2020 19:36
Show Gist options
  • Save zyxd/08fba1e439cf5d50d5a6cb5df9b3dfa8 to your computer and use it in GitHub Desktop.
Save zyxd/08fba1e439cf5d50d5a6cb5df9b3dfa8 to your computer and use it in GitHub Desktop.
import {
add,
compose,
concat,
curry,
join,
length,
map,
nth,
repeat,
replace,
split,
take,
takeWhile,
transpose,
trim,
unapply,
reduce
} 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 function(node, { delay, speed = 50, clean = false }) {
let children = Array.from(node.childNodes)
.filter(({ nodeType }) => nodeType === Node.ELEMENT_NODE || nodeType === Node.TEXT_NODE)
.map(({ textContent }) => trim(textContent))
.filter(text => text.length > 0)
if (clean) {
children = [...children, '']
}
const text = diffAll(children)
const duration = text.length * speed
return {
delay,
duration,
tick: t => {
const i = ~~(text.length * t)
node.textContent = clear(take(i, text))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment