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

word-wave

v1.1.0

Published

High-performance canvas text wave animation driven by simplex noise

Readme

word-wave

A high-performance canvas animation engine that renders floating text particles in a simplex-noise-driven wave pattern.

Live demo | npm

Features

  • WebGL 2 instanced rendering — all particles drawn in a single GPU draw call, with automatic Canvas 2D fallback
  • Pre-built glyph atlas for characters and whole words (no per-frame fillText)
  • Simplex noise sampled on a coarse grid and bilinearly interpolated per particle
  • Directional "beach wave" effect layered on top of the noise field
  • Automatic IntersectionObserver pause when off-screen
  • ResizeObserver for responsive canvas sizing
  • prefers-reduced-motion support (renders a static pattern)
  • CSS custom property theming (--word-wave-color, --word-wave-opacity)
  • Framework-agnostic — works with vanilla JS, Angular, React, Vue, etc.

Install

npm install word-wave

Usage

import { WordWaveEngine } from 'word-wave';

const canvas = document.getElementById('wave') as HTMLCanvasElement;
const engine = new WordWaveEngine(canvas, {
  words: ['dark_mode', 'feature_flag', 'rollout'],
  speed: 0.015,
});

// Later:
engine.stop();    // pause
engine.start();   // resume
engine.destroy(); // full cleanup

The canvas must be inside a positioned parent element — the engine sizes itself to fill canvas.parentElement.

Options

All fields are optional. Unspecified fields use sensible defaults.

| Option | Type | Default | Description | |--------|------|---------|-------------| | words | string[] | Feature-flag names | Words displayed as floating text particles | | frequency | number | 0.008 | Noise field spatial frequency (lower = smoother) | | amplitude | number | 10 | Maximum noise-driven displacement (CSS px) | | speed | number | 0.01 | How fast the noise field evolves over time | | spacingX | number | 90 | Horizontal spacing between word centers (CSS px) | | spacingY | number | 20 | Vertical spacing between rows (CSS px) | | direction | number | 225 | Wave propagation direction in degrees | | propagation | number | 0.03 | Wave density (higher = more crests) | | waveAmplitude | number | 15 | Directional wave push distance (CSS px) | | font | string | '14px system-ui, ...' | CSS font shorthand | | respectReducedMotion | boolean | true | Static pattern if prefers-reduced-motion: reduce | | pauseOffScreen | boolean | true | Pause animation when canvas is not visible | | mode | 'character' \| 'word' | 'character' | Per-character or per-word displacement |

Color & Opacity

Color and opacity are controlled via CSS custom properties on the canvas element, not JS options. This lets you use standard CSS for theming (media queries, class toggles, CSS variables).

| Property | Default | Description | |----------|---------|-------------| | --word-wave-color | inherited color | Text color (any CSS color value) | | --word-wave-opacity | 0.15 | Base particle opacity (01) |

The engine reads these once at construction. To update, set the properties and recreate the engine.

Example: light/dark theming

canvas {
  --word-wave-color: #1e1e1e;
  --word-wave-opacity: 0.24;
}

@media (prefers-color-scheme: dark) {
  canvas {
    --word-wave-color: #a5a5a5;
    --word-wave-opacity: 0.12;
  }
}
// Recreate on scheme change to pick up new CSS values
const mq = window.matchMedia('(prefers-color-scheme: dark)');
mq.addEventListener('change', () => {
  engine.destroy();
  engine = new WordWaveEngine(canvas, opts);
});

If no CSS custom properties are set, the engine falls back to the canvas element's inherited CSS color for text color, and 0.15 for opacity.

Built with AI

This project was vibe-engineered with Claude (Anthropic) under human review and direction throughout.

License

MIT