Discrete phrase-state cycling. Replaces the entire element's text with phrase A, then phrase B,
etc., at a fixed interval, then settles on finalText. Useful for loading screens,
boot sequences, and "decrypting" preambles. Provided by src/lib/phrase-cycle.js.
3-way distinction: TypingAnimation grows the string char-by-char (streaming/typed, string length increases). DecryptReveal shows the string at final length, scrambled, resolving left-to-right (char-level). PhraseCycle replaces the entire element text each tick — string length may vary between phrases.
Cycles through status phrases and settles on a final "ready" message. interval: 400ms.
Initializing → Connecting → Authenticating → Ready.
const cycle = new PhraseCycle(element, {
phrases: ['Initializing...', 'Connecting...', 'Authenticating...'],
interval: 400,
finalText: 'Ready.',
});
cycle.start();
System boot preamble with a welcome message as the final settled state. interval: 500ms.
BIOS check → Loading kernel → Mounting filesystems → Welcome
const boot = new PhraseCycle(element, {
phrases: [
'BIOS check OK',
'Loading kernel...',
'Mounting filesystems...',
'Starting services...',
],
interval: 500,
finalText: 'WELCOME.',
});
boot.start();
Loops indefinitely with no finalText. Perfect for persistent loading indicators. interval: 300ms.
loop: true — cycles forever, ignores duration and finalText
const spinner = new PhraseCycle(element, {
phrases: ['Loading.', 'Loading..', 'Loading...'],
interval: 300,
loop: true, // cycle forever — no finalText, no duration limit
});
spinner.start();
import { PhraseCycle } from '@whykusanagi/corrupted-theme/phrase-cycle';
// ── Settling cycle (default): one full pass then display finalText ─────────
const cycle = new PhraseCycle(element, {
phrases: ['Initializing...', 'Connecting...', 'Authenticating...'],
interval: 400, // ms between phrase swaps (default: 200)
duration: null, // null = phrases.length × interval (one full pass)
finalText: 'Ready.', // text written after settle; null = leave last phrase
loop: false, // false = settle after duration (default)
});
cycle.start(); // idempotent — safe to call while already running
// ── Looping (no settle): cycle forever ───────────────────────────────────
const spinner = new PhraseCycle(element, {
phrases: ['Loading.', 'Loading..', 'Loading...'],
interval: 300,
loop: true, // ignores duration + finalText
});
spinner.start();
spinner.stop(); // pause; leaves last phrase visible; reusable
spinner.start(); // restart from first phrase
// ── Lifecycle ─────────────────────────────────────────────────────────────
cycle.stop(); // stop timers; last phrase stays visible; reusable
cycle.destroy(); // teardown + release element reference; not reusable
cycle.isRunning(); // → boolean