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

sloteffect

v1.1.0

Published

Slot-machine-style rolls for numbers, letters, and text in React. Dependency-free, accessible, reduced-motion aware.

Readme

sloteffect

Slot-machine-style rolls for numbers, letters, and text in React. Each digit or character is its own reel that rolls up or down to its new value, wrapping through the charset, with a springy settle.

  • Dependency-free — React is the only peer dependency (Web Animations API + a precomputed CSS linear() spring; no animation library, no JS spring loop).
  • Three componentsSlotNumber, SlotLetter, SlotText.
  • Directionaldirection="both" (random per reel, default), "up", or "down".
  • Lean at rest — a character is a single glyph until it changes; the rolling strip is built only for the duration of a transition, then removed. Unchanged cells never animate, so a hero number costs a handful of DOM nodes, not hundreds.
  • Any text, any directionSlotText segments by grapheme (emoji, combining marks, surrogate pairs stay intact), keeps natural spacing/kerning, and orders LTR or RTL automatically.
  • Accessible — the value is the aria-label; reels are presentational; prefers-reduced-motion snaps instantly.
  • Tiny — ~5 KB ESM, tree-shakeable, ships ESM + CJS + types.

SlotNumber rolling through currency values like a slot machine

▶ Live demo


Install

# https://www.npmjs.com/package/sloteffect

bun add sloteffect
npm i sloteffect
pnpm add sloteffect
yarn add sloteffect

React 18 or 19 is a peer dependency.

Quick start

import { SlotNumber, SlotLetter, SlotText } from "sloteffect";

// Currency / percent / compact — anything Intl.NumberFormat can format
<SlotNumber value={total} format={{ style: "currency", currency: "USD", maximumFractionDigits: 0 }} />

// A single rolling character
<SlotLetter char={grade} />

// An arbitrary string: letters and digits roll, the rest stays put
<SlotText text="JACKPOT 7" />

Place a component inside a styled element — it inherits font-family, font-size, and color from the parent.


Components

SlotNumber

Formats a value with Intl.NumberFormat (plus an optional suffix) and rolls the digits. Separators, currency symbols, and the suffix stay static. Accepts any number (decimals, negatives, NaN/Infinity), a bigint, or an already-formatted string (passed through verbatim).

<SlotNumber value={0.813} format={{ style: "percent", minimumFractionDigits: 1 }} />   // 81.3%
<SlotNumber value={1234.5} format={{ style: "currency", currency: "USD" }} cents counter />  // $1,234.⁵⁰
<SlotNumber value={9007199254740993n} />                                               // bigint

| Prop | Type | Default | Description | |---|---|---|---| | value | number \| bigint \| string | — | Number/bigint to format, or a preformatted string. | | format | Intl.NumberFormatOptions | — | Style, currency, fraction digits, etc. | | locales | string \| string[] | "en-US" | BCP 47 locale(s). | | suffix | string | "" | Static text appended after the number (e.g. "/yr"). | | direction | "both" \| "up" \| "down" | "both" | Roll direction. | | randomSpin | boolean | false | Stagger each digit's spin/settle randomly per play. | | cents | boolean | false | Render the two fractional digits at 90% size, bottom-aligned (the decimal point stays full size). Forces two fraction digits. | | counter | boolean | false | Roll the digits like a gear-reduction odometer: each rolls from the previous value by however many of its own place-steps the value crossed, so low digits blur while the ten-thousands and up barely move. Best for a value that changes continuously (e.g. a slider); pass a stable format reference. | | className / style | — | — | Passed to the container. |

cents and counter read the value's digit places via Intl.NumberFormat.formatToParts; they're skipped when value is a preformatted string.

SlotLetter

A single character rolling through its case's alphabet (A–Z or a–z), wrapping around. Non-letters render static.

<SlotLetter char="Q" direction="up" />

| Prop | Type | Default | Description | |---|---|---|---| | char | string | — | The character to display. | | direction | "both" \| "up" \| "down" | "both" | Roll direction. | | className / style | — | — | Passed to the container. |

SlotText

Animates any string in any script. The text is split into grapheme clusters, and each cluster is a slot cell: digits and same-case Latin letters roll through their charset, while every other glyph (other scripts, emoji, punctuation) flips cleanly to its new value. At rest each cell is normal text, so spacing, kerning, and LTR/RTL ordering are correct; cells are right-anchored so trailing positions keep rolling as the string grows or shrinks.

<SlotText text="Level 12" direction="down" />
<SlotText text="東京タワー" />          // CJK
<SlotText text="שלום עולם" />          // right-to-left, auto-detected

| Prop | Type | Default | Description | |---|---|---|---| | text | string \| number \| bigint | — | The string to display. | | direction | "both" \| "up" \| "down" | "both" | Roll direction. | | dir | "auto" \| "ltr" \| "rtl" | "auto" | Writing direction; auto infers it from the content. | | className / style | — | — | Passed to the container. |

Note on connected scripts. Because each grapheme animates in its own cell, scripts with contextual joining (e.g. Arabic) render in isolated forms while rolling. Latin, CJK, Hebrew, emoji, and digits are unaffected.


Direction

Every component accepts direction:

| Value | Behavior | |---|---| | "both" (default) | Each reel flips a coin — up or down — independently. | | "up" | All reels roll upward (charset index increases), wrapping. | | "down" | All reels roll downward, wrapping. |


Integration notes

  • Use tabular-nums. Set font-variant-numeric: tabular-nums on the parent so digits keep an identical width and the layout doesn't shiver.
  • Line-height lives outside. Reel cells are exactly 1em tall; give the parent line-height ≥ 1.15 (serif faces especially) so nothing clips.
  • Reserve it for hero numbers. Animate key stats and answer-numbers — not tables, axis ticks, or tooltips that re-render wholesale.
  • Reduced motion. Under prefers-reduced-motion: reduce the reels snap to the final value with no animation. (Headless/preview browsers often report reduced motion — stub matchMedia to observe the roll in tests.)
  • Ordered vs. flip. Latin 0–9 / A–Z / a–z roll through their charset (the authentic reel). Any other glyph pair (other scripts, emoji, cross-charset) flips directly from old to new. For non-Latin numerals that should roll like digits, format with the nu-latn numbering system.

Development

bun install
bun run typecheck   # tsc --noEmit (strict)
bun run lint        # biome check
bun run test        # vitest (direction/wraparound logic)
bun run build       # tsup → dist/ (ESM + CJS + .d.ts)

The showcase (index.html) is a single, build-free file deployed to GitHub Pages by .github/workflows/pages.yml.

License

MIT © Jauder Ho