Use Scramble

PreviousNext

The use-scramble hook.

Docs
animbitslib

Preview

Loading preview…
lib/use-scramble.ts
import * as React from "react";

export interface UseScrambleOptions {
  text?: string;
  duration?: number;
  delay?: number;
  scrambleChars?: string;
}

export function useScramble(options: UseScrambleOptions): string {
  const {
    text = "",
    duration = 0.8,
    delay = 0,
    scrambleChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()",
  } = options;

  const [displayText, setDisplayText] = React.useState(text);

  React.useEffect(() => {
    const iterations = Math.floor(duration * 60); // 60fps
    let currentIteration = 0;

    const timeout = setTimeout(() => {
      const interval = setInterval(
        () => {
          if (currentIteration >= iterations) {
            setDisplayText(text);
            clearInterval(interval);
            return;
          }

          const progress = currentIteration / iterations;
          const newText = text
            .split("")
            .map((char, index) => {
              if (char === " ") return " ";
              if (index / text.length < progress) {
                return char;
              }
              return scrambleChars[
                Math.floor(Math.random() * scrambleChars.length)
              ];
            })
            .join("");

          setDisplayText(newText);
          currentIteration++;
        },
        (duration * 1000) / iterations,
      );

      return () => clearInterval(interval);
    }, delay * 1000);

    return () => clearTimeout(timeout);
  }, [text, duration, delay, scrambleChars]);

  return displayText;
}

Installation

npx shadcn@latest add @animbits/hooks-use-scramble

Usage

import { HooksUseScramble } from "@/lib/hooks-use-scramble"
HooksUseScramble()