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

@amonratcha/minimal-spinner

v0.0.1

Published

A small, zero-dependency CLI spinner for Node.js

Readme

@ash-alt-max/spinner

A tiny, zero-dependency spinner library for Node.js and browsers. This package provides:

  • A CLI (Node) spinner (Node/TTY).
  • A browser/DOM spinner (for web apps).
  • A small API for start/stop/update/succeed/fail that works in both environments.

Note: For Angular and other frontend frameworks, use the browser bundle (ESM) or import the browser entry path.


Install

# npm
npm install @ash-alt-max/spinner

# or yarn
yarn add @ash-alt-max/spinner

Quick usage — Browser (vanilla JS)

This library ships a browser-friendly ES module (e.g. dist/browser.js). If your package.json exports / browser field points to it, you can simply:

<script type="module">
import Spinner from '/node_modules/@ash-alt-max/spinner/dist/browser.js';

const area = document.getElementById('demo-area');
const s = new Spinner({ container: area, text: 'Loading...', interval: 100 });

s.start();
setTimeout(() => s.succeed('Done!'), 2000);
</script>

If you bundle your app (Vite/Rollup/webpack), you can import:

import Spinner from '@ash-alt-max/spinner/dist/browser.js';
// or, if package exports are configured:
// import Spinner from '@ash-alt-max/spinner';

Quick usage — Node (CLI)

The Node spinner is designed for TTY (terminal). Example:

// CommonJS
const Spinner = require('@ash-alt-max/spinner').default;

const s = new Spinner({ text: 'Processing...', interval: 80 });
s.start();

setTimeout(() => s.succeed('Completed'), 2000);

If you use TypeScript / ESM:

import Spinner from '@ash-alt-max/spinner';
const s = new Spinner({ text: 'Processing...' });
s.start();

Using in Angular

  1. Install the package (see Install section).
  2. Use the browser build inside a component (ensure client-side only; guard for SSR).

Example component (TypeScript):

// src/app/spinner-demo/spinner-demo.component.ts
import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
// Import browser bundle path; change if your package exports browser entry
import Spinner from '@ash-alt-max/spinner/dist/browser.js';

@Component({
  selector: 'app-spinner-demo',
  templateUrl: './spinner-demo.component.html',
})
export class SpinnerDemoComponent implements OnInit, OnDestroy {
  @ViewChild('spinnerHost', { static: true }) host!: ElementRef<HTMLDivElement>;
  private spinner!: any;

  ngOnInit(): void {
    this.spinner = new Spinner({
      container: this.host.nativeElement,
      text: 'Loading...',
      interval: 100
    });
  }

  start(): void { this.spinner.start(); }
  stop(): void { this.spinner.stop(); }
  succeed(): void { this.spinner.succeed('Completed'); }
  fail(): void { this.spinner.fail('Failed'); }
  updateText(t: string): void { this.spinner.update(t); }

  ngOnDestroy(): void {
    this.spinner?.stop(true);
  }
}

Template:

<!-- src/app/spinner-demo/spinner-demo.component.html -->
<div #spinnerHost></div>
<button (click)="start()">Start</button>
<button (click)="stop()">Stop</button>
<button (click)="succeed()">Succeed</button>
<button (click)="fail()">Fail</button>

Important: If your Angular app uses Server-Side Rendering (Angular Universal), ensure you only construct/start the spinner on the client. Use isPlatformBrowser or ngIf to prevent server execution.


API

Constructor options:

  • frames?: string[] — custom frames
  • interval?: number — ms between frames (default: 80)
  • text?: string — initial text
  • container?: HTMLElement — browser DOM container (browser build)
  • stream?: NodeJS.WriteStream — stdout or custom stream (Node build)
  • hideCursor?: boolean — (Node) hide cursor while spinning

Instance methods:

  • start(text?: string): this
  • stop(clear = true): this
  • succeed(text?: string): this
  • fail(text?: string): this
  • update(text: string): this
  • isSpinning(): boolean

Build (author)

If you maintain this package locally and want to produce a browser bundle:

Using esbuild (example):

# install dev deps
npm install -D esbuild

# build browser bundle (ESM)
npx esbuild src/browser.ts --bundle --format=esm --target=es2017 --outfile=dist/browser.js

Suggested package.json snippets:

{
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "browser": "dist/browser.js",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.esm.js",
      "require": "./dist/index.cjs.js",
      "default": "./dist/browser.js"
    }
  },
  "scripts": {
    "build": "tsc -p tsconfig.json && npm run build:browser",
    "build:browser": "esbuild src/browser.ts --bundle --format=esm --target=es2017 --outfile=dist/browser.js",
    "prepare": "npm run build"
  }
}

When browser / exports are set, bundlers and frameworks will prefer the browser entry for frontend builds.


Examples

  • examples/index.html — demo for the browser spinner
  • examples/run.js — demo for Node (uses compiled dist/index.js)

Run the browser demo locally:

# start a simple static server in the project root
npx serve examples
# or
python -m http.server --directory examples 8000
# then open http://localhost:5000/examples/index.html (port depends on tool)

Testing

We use Vitest for unit tests (running against source TypeScript):

npm install
npm test          # runs vitest --run
npm run test:watch

Notes, SSR and compatibility

  • The Node spinner requires a TTY (stdout.isTTY). When used in non-TTY environments, it falls back to printing a single-line message.
  • The browser build manipulates the DOM and must only be used in client-side contexts.
  • Provide type declarations (.d.ts) so TypeScript consumers (including Angular) get typing support.

Contributing

PRs welcome — please add tests and keep the bundle small. See LICENSE for licensing.


License

MIT