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

lite-viewport

v1.0.1

Published

Zero-dependency canvas scaling and resize manager with DPR handling, ResizeObserver, and cumulative-scaling fix.

Readme

lite-viewport

npm version npm bundle size npm downloads npm total downloads TypeScript Zero Dependencies License: MIT

A zero-dependency canvas scaling and resize manager that handles devicePixelRatio and CSS layout changes automatically.

No more blurry canvases on Retina screens or manual resize listeners that miss flex/grid reflows.

Features

  • DPR-aware sizing — sharp rendering on Retina/HiDPI displays
  • ResizeObserver-based — responds to CSS flex/grid changes, not just window resize
  • Transform reset — prevents the cumulative scaling bug on repeated resizes
  • contextOptions passthrough — supports willReadFrequently, alpha: false, etc.
  • Clean teardowndestroy() disconnects observer and releases references
  • Zero dependencies, < 1 KB

Installation

npm install lite-viewport

Quick Start

import { Viewport } from 'lite-viewport';

const canvas = document.querySelector('canvas');

const viewport = new Viewport({
    canvas,
    onResize(width, height, dpr) {
        console.log(`Canvas: ${width}×${height} @ ${dpr}x`);
    },
});

// Canvas is now sized to its parent, scaled for DPR,
// and will auto-resize when the parent's CSS dimensions change.

// Later: clean up
viewport.destroy();

Options

const viewport = new Viewport({
    canvas: myCanvas,             // Required: the canvas element
    autoResize: true,             // Watch parent via ResizeObserver (default: true)
    onResize: (w, h, dpr) => {}, // Called after each resize
    contextOptions: {             // Passed to getContext('2d', ...)
        willReadFrequently: true, // Optimize for getImageData-heavy usage
        alpha: false,             // Opaque canvas (slight perf boost)
    },
});

API

| Method | Description | |--------|-------------| | new Viewport(options) | Create and perform initial resize | | .resize() | Manually trigger a resize | | .destroy() | Disconnect observer, release references. Idempotent. |

| Property | Type | Description | |----------|------|-------------| | .width | number | Current CSS width | | .height | number | Current CSS height | | .dpr | number | Current devicePixelRatio | | .canvas | HTMLCanvasElement | The managed canvas (null after destroy) | | .ctx | CanvasRenderingContext2D | The 2D context (null after destroy) |

The Cumulative Scaling Bug

Most canvas resize code does this:

ctx.scale(dpr, dpr); // Called on every resize

After 3 resizes at DPR 2: scale(2) × scale(2) × scale(2) = scale(8). Everything is 4× too large.

lite-viewport fixes this by resetting the transform matrix first:

ctx.setTransform(1, 0, 0, 1, 0, 0); // Reset to identity
ctx.scale(dpr, dpr);                  // Apply fresh

TypeScript

import { Viewport, type ViewportOptions } from 'lite-viewport';

const vp = new Viewport({
    canvas: document.querySelector('canvas')!,
    contextOptions: { willReadFrequently: true },
    onResize(w, h, dpr) {
        // fully typed
    },
});

License

MIT