npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

texttweener

v1.0.0

Published

Animate text transitions by morphing individual letters to their new positions

Readme

TextTweener

Animate text transitions by morphing individual letters to their new positions. Shared letters fly to where they appear in the next text, while unique letters fade in and out — creating a unique "anagram solver" effect.

4.3KB gzipped. Zero dependencies. TypeScript. GPU-accelerated.

Available as npm package, WordPress Gutenberg Block, and After Effects Script.

Install

npm install texttweener

Or use a script tag:

<script src="https://unpkg.com/texttweener/dist/index.umd.min.js"></script>

Quick Start

<div id="hero">
  <span class="text">Build something great</span>
  <span class="text">Ship it to the world</span>
  <span class="text">Watch it grow</span>
</div>
import { TextTweener } from 'texttweener';

const tt = new TextTweener('#hero');

That's it. No fixed dimensions needed — the container sizes itself automatically.

Options

const tt = new TextTweener('#hero', {
  duration: 4000,            // ms each text is displayed (default: 4000)
  transitionDuration: 800,   // ms for the animation (default: 800)
  stagger: 15,               // ms delay between each letter (default: 15)
  easing: 'cubic-bezier(0.16, 1, 0.3, 1)',  // CSS easing (default)
  textAlign: 'left',         // 'left' | 'center' | 'right' (default: 'left')
  direction: 'forward',      // 'forward' | 'backward' | 'alternate'
  loop: true,                // loop when reaching the end (default: true)
  autoplay: true,            // start automatically (default: true)
  caseSensitive: true,       // 'A' only matches 'A', not 'a' (default: true)
  reduceMotion: true,        // respect prefers-reduced-motion (default: true)
});

Programmatic texts

Pass texts as an array instead of using DOM children:

const tt = new TextTweener('#hero', {
  texts: [
    'Über 30 Sonderzeichen: Klammern (rund), [eckig] & {geschweifte}!',
    'Preise: ab 9,99 € pro Monat. Fragen? E-Mail an [email protected]!',
    'Mathematik: 2 + 2 = 4, aber 100% der Lösung liegt im Detail...',
  ],
});

Full Unicode support — letters, numbers, special characters, umlauts, emoji.

API

tt.play()        // Start or resume playback
tt.pause()       // Pause playback
tt.resume()      // Resume (alias for play)
tt.next()        // Transition to next text (returns Promise)
tt.prev()        // Transition to previous text (returns Promise)
tt.goTo(2)       // Transition to specific index (returns Promise)
tt.destroy()     // Clean up and remove all listeners

tt.current       // Current text index (read-only)
tt.total         // Total number of texts (read-only)
tt.isPlaying     // Whether currently playing (read-only)

Events

tt.on('ready', () => { });
tt.on('beforeTransition', (from, to) => { });
tt.on('afterTransition', (from, to) => { });
tt.on('change', (currentIndex) => { });
tt.on('pause', () => { });
tt.on('resume', () => { });
tt.on('destroy', () => { });

// on() returns an unsubscribe function
const unsub = tt.on('change', (idx) => console.log(idx));
unsub(); // remove listener

How It Works

  1. Measure — All texts are rendered invisibly to capture the exact position of every letter. The container auto-sizes to fit — no fixed dimensions needed.
  2. Match — Letters shared between texts are paired using nearest-neighbor matching. Instead of matching the 3rd "e" to the 3rd "e", the algorithm finds the physically closest "e" — creating much more natural movement paths.
  3. Animate — Matched letters fly to their new positions via CSS transforms (GPU-accelerated). Unmatched letters fade out while new letters fade in simultaneously.

Platforms

npm / JavaScript

The core library. Works with any framework or vanilla JS.

npm install texttweener

WordPress

Gutenberg Block with full editor controls — text inputs, timing sliders, easing presets, alignment, font size. See wordpress/ for the plugin.

After Effects

ExtendScript panel that generates position and opacity keyframes for each character, using the same nearest-neighbor matching algorithm. See aftereffects/ for the script.

Accessibility

  • Creates an aria-live="polite" region that announces each text change to screen readers
  • Respects prefers-reduced-motion — falls back to a simple crossfade
  • Keyboard and screen reader friendly

Browser Support

All modern browsers (Chrome, Firefox, Safari, Edge). Requires Web Animations API support.

History

Originally built in 2016 as a jQuery plugin (v0.2). Completely rewritten in 2026 as a modern TypeScript library with zero dependencies, GPU-accelerated animations, auto-sizing, nearest-neighbor matching, and full API.

License

MIT — Michael Rademacher