svelte-typewriter
Version:
A simple and reusable typewriter effect for your Svelte applications
68 lines (57 loc) • 2.03 kB
JavaScript
import { getLongestTextElement } from '../helpers/getLongestTextElement'
import { writeEffect } from '../helpers/writeEffect'
import { onAnimationEnd } from '../helpers/onAnimationEnd'
import { animationSetup } from '../helpers/animationSetup'
// the name "default" cannot be used due to being a js keyword
/**
* @typedef {object} Props
* @property {number} [interval]
* @property {boolean} [cursor]
* @property {boolean} [keepCursorOnFinish]
* @property {number} [delay]
* @property {boolean} [showCursorOnDelay]
* @property {boolean} [disabled]
* @property {string} [element]
* @property {number} [scrambleDuration]
* @property {number} [scrambleSlowdown]
* @property {number} [unwriteInterval]
* @property {number} [wordInterval]
*/
/**
* @typedef {{ update: () => void, destroy: () => void }} SvelteActionReturnType
*/
/**
* @typedef {(node: HTMLElement, props: Props) => SvelteActionReturnType} TypewriterModeFn
*/
/**
* @type {TypewriterModeFn}
*/
const concurrent = (node, props) => {
const { options, elements } = animationSetup(node, props)
const lastElementToFinish = getLongestTextElement(elements)
onAnimationEnd(lastElementToFinish, () => options.dispatch('done'))
for (const element of elements) {
// "then" is required here to prevent blocking execution, thus keeping
// the animation asynchronous
writeEffect(element, options).then(() => {
if (options.keepCursorOnFinish) {
const isNotLongestElement = element.currentNode !== lastElementToFinish
isNotLongestElement
? element.currentNode.classList.replace('typing', 'finished-typing')
: options.dispatch('done')
} else {
element.currentNode.classList.replace('typing', 'finished-typing')
}
const cursorHasTimeout = typeof options.keepCursorOnFinish === 'number'
cursorHasTimeout &&
setTimeout(() => {
element.currentNode.classList.replace('typing', 'finished-typing')
}, options.keepCursorOnFinish)
})
}
return {
update() {},
destroy() {}
}
}
export default concurrent