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

@redesigner/wave.js

v1.3.0

Published

GPU-accelerated animated sine wave backgrounds. Vanilla JS + React. WebGL2 → Canvas 2D → CSS fallback. 60 FPS.

Readme

wave.js

GPU-accelerated animated sine wave backgrounds. Works with vanilla JS and React. Built with raw WebGL2 + custom GLSL shaders. Automatic fallback chain: WebGL2 → Canvas 2D → CSS gradient → solid color.

Full documentation: DOCS.md

Features

  • Zero dependencies for vanilla JS — no Three.js, no React required
  • WebGL2 GPU rendering at 60 FPS
  • Automatic fallback: WebGL2 → Canvas 2D (CPU) → CSS gradient (static) → solid color (none)
  • User-selectable renderer via renderer option or setRenderMode() at runtime
  • 12 adjustable parameters (waves, speed, amplitude, frequency, opacity, thickness, blur, concentration, randomness, thickness randomness, vertical offset, rotation)
  • 6 built-in color themes with automatic time-of-day selection
  • Custom RGBA color picker with per-color opacity
  • Glass effect, Liquid Metal effect, Split Fill mode, Bloom, Lumen, Twist
  • Rotation (0–360°) around screen center
  • Mouse-reactive wave distortion
  • Smooth 1500ms color transitions between themes
  • Film grain post-processing (WebGL only)
  • React component with built-in control panel
  • Responsive on mobile
  • Retina / HiDPI support (capped at 2x)

Installation

npm install @redesigner/wave.js

Vanilla JS

import { WaveBackground } from '@redesigner/wave.js'

const wave = new WaveBackground('#hero', {
  theme: 'sunset',
  waveCount: 12,
  speed: 0.5,
})

Force a specific renderer

// Force Canvas 2D (no GPU)
const wave = new WaveBackground('#hero', {
  renderer: 'canvas2d',
})

// Force no effects at all
const wave = new WaveBackground('#hero', {
  renderer: 'none',
  theme: 'night',
})

Switch renderer at runtime

wave.setRenderMode('canvas2d')  // Switch to CPU rendering
wave.setRenderMode('css')       // Static gradient
wave.setRenderMode('none')      // Solid background color
wave.setRenderMode('webgl2')    // Back to GPU

Update parameters

wave.setParam('waveCount', 20)
wave.setParam('amplitude', 0.1)
wave.setParam('rotation', 45)
wave.setTheme('night')
wave.setColors(['#ff0000', '#00ff00', '#0000ff', '#ffff00'])
wave.setSplitFill(true)
wave.setGlass(true)
wave.setLiquidMetal(true)

Cleanup

wave.destroy()

Plain HTML (no bundler)

<div id="hero" style="width: 100%; height: 100vh;"></div>
<script type="module">
  import { WaveBackground } from '@redesigner/wave.js'
  new WaveBackground('#hero', { theme: 'daytime' })
</script>

React

npm install @redesigner/wave.js react react-dom
import { HeroWave } from '@redesigner/wave.js/react'

function App() {
  return (
    <HeroWave theme="sunset">
      <h1>Your content here</h1>
    </HeroWave>
  )
}

The React component includes a built-in control panel with all sliders, color picker, effect toggles, and renderer selector.

Available props

| Prop | Type | Default | Description | |------|------|---------|-------------| | theme | string | auto (time-of-day) | Color theme name | | style | object | {} | Container inline styles | | className | string | — | Container CSS class | | children | ReactNode | — | Content rendered on top of the wave background |

API Reference

new WaveBackground(container, options?)

Creates an animated wave background in the given container.

container — DOM element or CSS selector string (e.g. '#hero').

options:

| Option | Default | Description | |--------|---------|-------------| | renderer | 'auto' | Renderer to use: 'auto', 'webgl2', 'canvas2d', 'css', or 'none' | | theme | auto (time-of-day) | Color theme: 'pre-dawn', 'sunrise', 'daytime', 'dusk', 'sunset', 'night' | | waveCount | 8 | Number of wave layers (1–100) | | speed | 0.3 | Animation speed (0–2) | | amplitude | 0.06 | Wave height (0–0.2) | | frequency | 2.5 | Wave density (0.5–10) | | opacity | 0.6 | Wave transparency (0–1) | | thickness | 1 | Wave solid core width in px (1–100) | | blur | 30 | Edge fade zone in px (0–200) | | concentration | 0 | Vertical compression toward center (0–50) | | randomness | 0 | Per-wave amplitude variation (0–1) | | thicknessRandom | 0 | Per-wave thickness variation (0–1) | | verticalOffset | 0 | Shift waves up/down (-0.5–0.5) | | rotation | 0 | Rotation in degrees (0–360) | | splitFill | false | One-directional fill mode | | glass | false | Glass transparency effect (WebGL only) | | liquidMetal | false | Chrome/metal effect (WebGL only) | | lmLiquid | 0.07 | Liquid Metal flow intensity (0–0.2) | | bloom | false | HDR bloom post-processing (WebGL only) | | bloomThreshold | 0.6 | Luminance above which bloom kicks in (0–1) | | bloomIntensity | 1.4 | Bloom halo strength (0–3) | | lumen | false | Glowing-ribbon render mode (WebGL only) | | lumenIntensity | 1 | Lumen brightness multiplier (0–2). >1 drives a stronger bloom halo. | | twist | false | 3D chrome/glass twisted-ribbon effect (WebGL only) | | twistAmount | 1 | Twist intensity (0–1) | | colors | — | Explicit 4-hex-color array. Overrides theme. | | colorOpacities | [1,1,1,1] | Per-color opacity array |

Methods

| Method | Description | |--------|-------------| | setRenderMode(mode) | Switch renderer: 'webgl2', 'canvas2d', 'css', or 'none' | | setTheme(name) | Switch color theme with 1500ms animated transition | | setColors(hexArray) | Set 4 custom hex colors with animated transition | | setParam(key, value) | Update any wave parameter instantly | | setColorOpacities(arr) | Set per-color opacity [0-1, 0-1, 0-1, 0-1] | | setSplitFill(bool) | Toggle split fill mode | | setGlass(bool) | Toggle glass effect | | setLiquidMetal(bool) | Toggle liquid metal effect | | setBloom(bool) | Toggle HDR bloom post-processing | | setLumen(bool) | Toggle glowing-ribbon render mode | | setTwist(bool) | Toggle 3D chrome twist effect | | toJSON() | Return current settings as a plain object (round-trips through new WaveBackground(el, json)) | | setConfig(obj) | Apply a settings object at runtime — mirror of what the constructor accepts | | destroy() | Stop animation, remove canvas, cleanup all event listeners |

Properties

| Property | Description | |----------|-------------| | renderMode | Current active renderer: 'webgl2', 'canvas2d', 'css', or 'none' | | params | Current parameter values object | | theme | Current theme name |

Renderers

| Mode | Description | GPU | Animated | Effects | |------|-------------|-----|----------|---------| | webgl2 | Full GPU shader rendering | Yes | Yes | All (glass, liquid metal, film grain) | | canvas2d | CPU-based line drawing | No | Yes | Waves, colors, opacity, rotation | | css | Static CSS gradient | No | No | Theme colors as gradient | | none | Solid background color | No | No | Background color only |

When renderer is set to 'auto' (default), the fallback chain is:

WebGL2 available? → GPU shader (60 FPS, all effects)
    ↓ no
Canvas 2D available? → CPU rendering (animated waves)
    ↓ no
CSS gradient (static theme colors)

You can check which renderer is active via wave.renderMode.

Themes

| Theme | Auto Time | Colors | |-------|-----------|--------| | pre-dawn | 05:00–08:00 | Deep purple, magenta, orange, gold | | sunrise | 08:00–11:00 | Dark purple, hot pink, orange, yellow | | daytime | 11:00–16:00 | Navy, blue, cyan, mint | | dusk | 16:00–20:00 | Dark purple, violet, lavender, light purple | | sunset | 20:00–23:00 | Deep purple, pink, coral, orange | | night | 23:00–05:00 | Near-black, dark purple, medium purple, violet |

When no theme is specified, the component automatically selects based on the user's local time and re-checks every 60 seconds.

To disable auto-detection, simply pass a theme option:

// Fixed theme — no auto-switching
new WaveBackground('#hero', { theme: 'sunset' })

// React — fixed theme
<HeroWave theme="sunset">...</HeroWave>

If the user manually selects a theme via the control panel, auto-detection is disabled until reset.

JSON config

Everything you tune in the playground at wavejs.org is just options — and the constructor accepts them all. Two flows:

A. Inline options (no JSON):

new WaveBackground('#hero', {
  theme: 'sunset', waveCount: 12, bloom: true, twist: true,
})

B. Export + load JSON. Tweak the playground to taste, click Copy JSON in the Parameters panel, paste into a config.json, and load at runtime:

// vanilla
const config = await fetch('/config.json').then(r => r.json())
const wave = new WaveBackground('#hero', config)
// React
import config from './config.json'
const wave = new WaveBackground(el, config)

The JSON shape matches the options 1-to-1 — no mapping layer:

{
  "renderer": "webgl2",
  "colors": ["#07070f", "#3730a3", "#06b6d4", "#34d399"],
  "colorOpacities": [1, 1, 1, 1],
  "waveCount": 4, "speed": 0.3, "amplitude": 0.08, "frequency": 2,
  "thickness": 50, "blur": 6, "opacity": 1,
  "bloom": false, "twist": true, "twistAmount": 1
}

Round-trip at runtime: wave.toJSON() returns the current settings; wave.setConfig(obj) applies one. See examples/vanilla/from-json.html and examples/react/src/AppFromJson.jsx for working samples.

Browser Support

  • Chrome 56+
  • Firefox 51+
  • Safari 15+
  • Edge 79+

Fallback renderers ensure the component works even in environments without WebGL.

Build

npm run build

License

MIT