UNPKG

@twistezo/react-text-scramble

Version:
224 lines (217 loc) 6.24 kB
var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __hasOwnProp = Object.prototype.hasOwnProperty; var __moduleCache = /* @__PURE__ */ new WeakMap; var __toCommonJS = (from) => { var entry = __moduleCache.get(from), desc; if (entry) return entry; entry = __defProp({}, "__esModule", { value: true }); if (from && typeof from === "object" || typeof from === "function") __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable })); __moduleCache.set(from, entry); return entry; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true, configurable: true, set: (newValue) => all[name] = () => newValue }); }; // src/index.ts var exports_src = {}; __export(exports_src, { default: () => TextScramble_default, createTextScramble: () => createTextScramble, TextScrambleAnimator: () => TextScrambleAnimator, TextScramble: () => TextScramble_default, SYMBOLS: () => SYMBOLS, DEFAULT_PAUSE_TIME: () => DEFAULT_PAUSE_TIME, DEFAULT_PAUSED: () => DEFAULT_PAUSED, DEFAULT_NEXT_LETTER_SPEED: () => DEFAULT_NEXT_LETTER_SPEED, DEFAULT_LETTER_SPEED: () => DEFAULT_LETTER_SPEED }); module.exports = __toCommonJS(exports_src); // src/TextScramble.tsx var import_react = require("react"); // src/constants.ts var DEFAULT_LETTER_SPEED = 5; var DEFAULT_NEXT_LETTER_SPEED = 100; var DEFAULT_PAUSE_TIME = 1500; var DEFAULT_PAUSED = false; var SYMBOLS = "!<>-_\\/[]{}—=+*^?#".split(""); // src/utils.ts var randomItem = (array) => array[Math.floor(Math.random() * array.length)]; var nextItem = (array, currentItem) => { const currentIndex = array.indexOf(currentItem); const bound = array.length; const nextIndex = (currentIndex + bound + 1) % bound; return array[nextIndex]; }; // src/TextScrambleAnimator.ts class TextScrambleAnimator { bakeLetterInterval = null; bakeTextInterval = null; currentText; displayedText; element; leftIndexes = []; letterSpeed; nextLetterSpeed; paused; pauseTime; pauseTimeout = null; texts; constructor(element, options) { this.element = element; this.texts = options.texts; this.letterSpeed = options.letterSpeed ?? DEFAULT_LETTER_SPEED; this.nextLetterSpeed = options.nextLetterSpeed ?? DEFAULT_NEXT_LETTER_SPEED; this.pauseTime = options.pauseTime ?? DEFAULT_PAUSE_TIME; this.paused = options.paused ?? DEFAULT_PAUSED; this.currentText = this.texts[0]; this.displayedText = this.initSymbols(); this.render(); if (!this.paused) { this.animate(); } } destroy() { this.clearAllIntervals(); } pause() { this.paused = true; if (this.pauseTimeout) { clearTimeout(this.pauseTimeout); this.pauseTimeout = null; } } play() { this.paused = false; this.clearAllIntervals(); this.animate(); } reset() { this.clearAllIntervals(); this.currentText = this.texts[0]; this.displayedText = this.initSymbols(); this.render(); this.leftIndexes = []; if (!this.paused) { this.animate(); } } setTexts(texts) { this.texts = texts; this.reset(); } animate() { this.bakeText(); } bakeLetter() { this.bakeLetterInterval = setInterval(() => { if (!this.paused) { const updatedText = []; this.currentText.split("").forEach((char, i) => { if (!this.leftIndexes.includes(i)) { updatedText[i] = this.currentText[i]; return; } updatedText[i] = randomItem(SYMBOLS); }); this.displayedText = updatedText; this.render(); } }, this.letterSpeed); } bakeText() { this.leftIndexes = this.currentText.split("").map((_, i) => i); this.bakeLetter(); this.bakeTextInterval = setInterval(() => { if (!this.paused) { if (this.leftIndexes.length === 0) { this.clearAllIntervals(); this.pauseTimeout = setTimeout(() => { this.currentText = nextItem(this.texts, this.currentText); this.displayedText = this.initSymbols(); this.render(); this.animate(); }, this.pauseTime); return; } this.leftIndexes.shift(); } }, this.nextLetterSpeed); } clearAllIntervals() { if (this.bakeLetterInterval) { clearInterval(this.bakeLetterInterval); this.bakeLetterInterval = null; } if (this.bakeTextInterval) { clearInterval(this.bakeTextInterval); this.bakeTextInterval = null; } if (this.pauseTimeout) { clearTimeout(this.pauseTimeout); this.pauseTimeout = null; } } initSymbols() { return Array(this.currentText.length).fill(0).map(() => randomItem(SYMBOLS)); } render() { this.element.textContent = this.displayedText.join(""); } } function createTextScramble(element, options) { return new TextScrambleAnimator(element, options); } // src/TextScramble.tsx var jsx_dev_runtime = require("react/jsx-dev-runtime"); var TextScramble = ({ className, letterSpeed, nextLetterSpeed, paused, pauseTime, texts }) => { const elementRef = import_react.useRef(null); const animatorRef = import_react.useRef(null); import_react.useEffect(() => { if (!elementRef.current) return; animatorRef.current = new TextScrambleAnimator(elementRef.current, { letterSpeed, nextLetterSpeed, paused, pauseTime, texts }); return () => { animatorRef.current?.destroy(); }; }, [texts, letterSpeed, nextLetterSpeed, pauseTime]); import_react.useEffect(() => { if (!animatorRef.current) return; if (paused) { animatorRef.current.pause(); } else { animatorRef.current.play(); } }, [paused]); return /* @__PURE__ */ jsx_dev_runtime.jsxDEV("div", { className, ref: elementRef }, undefined, false, undefined, this); }; var TextScramble_default = TextScramble;