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

colab-smooth-scroll

v0.2.0

Published

Lerp-based smooth scrolling for the web. Vanilla JS, zero dependencies.

Readme

colab-smooth-scroll

Lerp-based smooth scrolling. Vanilla JS, zero dependencies.

Wheel input feeds a virtual scroll target that the real scroll position eases toward each frame, so the page glides instead of stepping. Touch drags, keyboard, scrollbar, and anchor jumps stay native — a scroll listener adopts any position the library didn't set itself. Respects prefers-reduced-motion.

Install

npm install colab-smooth-scroll

Usage

ESM / bundler

import { initSmoothScroll } from 'colab-smooth-scroll';

const scroller = initSmoothScroll({ smoothness: 0.07 });

scroller.stop();                      // freeze wheel-driven scrolling
scroller.start();                     // resume it
scroller.scrollTo(0, { duration: 1.4 }); // animate to a position
scroller.on('scroll', ({ scroll, velocity }) => { /* ... */ });

// later, if needed
scroller.destroy();

CommonJS

const { initSmoothScroll } = require('colab-smooth-scroll');

Plain <script>

<script src="https://unpkg.com/colab-smooth-scroll/dist/index.global.js"></script>
<script>
  const scroller = window.SmoothScroll.initSmoothScroll({ smoothness: 0.07 });
</script>

Options

| Option | Type | Default | Description | | ------------------ | -------- | ---------------- | -------------------------------------------------------------------- | | smoothness | number | 0.07 | Wheel easing rate per frame — higher is snappier. | | wheelMultiplier | number | 1 | Scales the wheel delta before it's applied. | | scrollToDuration | number | 1.2 | Default duration (seconds) for scrollTo() calls that don't set one.| | scrollToEasing | function | ease-out expo | Default easing for scrollTo() calls that don't set one. |

Instance methods

initSmoothScroll() returns an instance (or an inert no-op instance if prefers-reduced-motion is on):

  • stop() / start() — freeze/resume wheel-driven scrolling. While stopped, wheel input is swallowed (preventDefault, no movement) except on elements opted out via data-wheel-native. Toggles is-smooth-scroll-stopped on <html>.
  • scrollTo(y, { duration, easing }) — animates to position y. duration: 0 jumps instantly. A wheel event mid-animation interrupts it and resumes normal wheel-driven scrolling from wherever it was.
  • on('scroll', fn) / off('scroll', fn)fn is called each frame the position changes with { scroll, velocity } (velocity is the pixel delta since the previous frame).
  • destroy() — removes all listeners and stops the animation loop.

<html> carries is-smooth-scroll for as long as the instance is active (added on init, removed on destroy()), plus two transient classes: is-smooth-scrolling while a scroll animation (wheel-driven or scrollTo()) is in flight, and is-smooth-scroll-stopped while stop() is active. Compose .is-smooth-scroll.is-smooth-scroll-stopped (two classes) in consumer CSS when a rule needs to outrank another same-specificity rule without depending on source order.

Opting an element out

Elements that scroll themselves (e.g. a fixed thumb rail, or a modal panel with its own overflow) can opt their wheel input out of the page-scroll hijack:

<div data-wheel-native>...</div>

Build

npm run build

Bundling: math.js, ticker.js, and index.js have no circular deps, so build.js strips their import/export lines and concatenates them in dependency order, then runs the result through terser — the same minifier d8e uses for JS — for the ESM, CJS, and global (<script>) dist builds. terser is the only build-time dependency.

Test

npm test

Uses Node's built-in test runner (node --test), zero test dependencies. The library only touches a handful of window/document members, so test-helper/browser-env.js hand-rolls a minimal stub rather than pulling in jsdom.