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

@linear_non/stellar-libs

v1.6.13

Published

Reusable JavaScript libraries for Non-Linear Studio projects.

Readme

stellar-libs

@linear_non/stellar-libs — Reusable UI behavior modules for Non-Linear Studio projects.

A collection of lightweight, self-contained frontend UI behavior modules built to work seamlessly with @linear_non/stellar-kit. Each library provides specific functionality and can be dropped into modular websites with minimal configuration.

Available Libraries

| Library | Description | |---|---| | Sticky | Sticky scroll behavior with GSAP ScrollTrigger | | Smooth | Smooth scroll system using VirtualScroll | | SplitOnScroll | Text splitting with scroll-triggered reveals | | Noise | Canvas-based animated noise effect | | SpritePlayer | Image sequence player on canvas | | CursorTracker | Custom cursor that follows mouse | | Marquee | Infinite horizontal marquee scroller | | Slider | Drag slider with optional infinite loop and progress | | ScrollTo | Declarative click-to-scroll via data attributes |

Installation

npm install @linear_non/stellar-libs
npm install @linear_non/stellar-kit

Local Development

npm install
npm run dev

Launches a Vite dev server with a demo index linking to individual playgrounds for each library.

Symlink into a project

To test local changes in a real project (e.g. nonlinear-v2) without publishing:

# 1. Create a global link from stellar-core
cd stellar-core/packages/libs
pnpm link --global

# 2. Consume the link in your project
cd your-project
pnpm link --global @linear_non/stellar-libs

# 3. Unlink when done (restores the npm version)
cd your-project
pnpm unlink @linear_non/stellar-libs
pnpm install

Usage

Sticky

import { Sticky } from "@linear_non/stellar-libs"

const sticky = new Sticky({
  el: document.querySelector(".sticky-container"),
  sticky: document.querySelector(".sticky-element"),
  isSmooth: false,
  onUpdateCallback: ({ progress }) => console.log(progress),
})

In non-smooth mode, Sticky uses native CSS position: sticky — no -fixed class needed. In smooth mode, ScrollTrigger handles positioning via transforms.

Smooth

import { Smooth } from "@linear_non/stellar-libs"

const smooth = new Smooth({ scroll: kitStore.scroll })
<section data-smooth data-speed="0.8">Parallax content</section>

SplitOnScroll

import { SplitOnScroll } from "@linear_non/stellar-libs"

const split = new SplitOnScroll({
  el: document.querySelector(".trigger"),
  splitText: document.querySelectorAll("h1"),
  isReady: ({ splits, groups }) => {
    gsap.from(splits[0].chars, { y: 40, opacity: 0, stagger: 0.03 })
  },
  once: true,
})

The constructor key is splitText (not splitTargets). The isReady callback receives { splits, groups }.

Noise

import { Noise } from "@linear_non/stellar-libs"

const noise = new Noise({
  target: ".noise-canvas",
  density: 0.75,
  color: 0xf3f2feff,
  opacity: 0.25,
  fps: 24,
})

SpritePlayer

import { SpritePlayer } from "@linear_non/stellar-libs"

const player = new SpritePlayer({
  canvas: document.querySelector("canvas"),
  container: document.querySelector(".player-container"),
  desktop_path: "/sprites/desktop/",
  mobile_path: "/sprites/mobile/",
  fileName: "frame_",
  total: 60,
  priorityFrames: 30, // load first 30 frames, rest in background (default: min(30, total))
})

// init() is called automatically by the constructor
// listen for sprite:ready (phase 1 done) or sprite:loaded (all frames done)
player.setProgress(0.5)

CursorTracker

import { CursorTracker } from "@linear_non/stellar-libs"

const tracker = new CursorTracker({
  container: document.querySelector(".hover-area"),
  el: document.querySelector(".cursor"),
  ease: 0.12,
  isCentered: true,
})

// Custom hover animation (optional — defaults to autoAlpha fade)
const tracker = new CursorTracker({
  container: document.querySelector(".hover-area"),
  el: document.querySelector(".cursor"),
  animation: {
    in: (el) => gsap.to(el, { autoAlpha: 1, scale: 1, duration: 0.4, ease: "back.out" }),
    out: (el) => gsap.to(el, { autoAlpha: 0, scale: 0.5, duration: 0.3 }),
  },
})

CursorTracker subscribes to APP_TICK internally — do not add an external tick subscription.

Marquee

import { Marquee } from "@linear_non/stellar-libs"

const marquee = new Marquee({
  container: document.querySelector(".marquee"),
  el: document.querySelector(".marquee__track"),
  speed: 50,
  gap: "1.6rem",
})

Slider

import { Slider } from "@linear_non/stellar-libs"

const slider = new Slider({
  container: document.querySelector(".slider"),
  el: document.querySelector(".slider__track"),
  speed: 0.1,
  snap: true,
  infinite: false,
  activeBelow: 'mediumUp', // only active below the mediumUp breakpoint; mobileOnly:true is an alias
  prevEl: document.querySelector(".prev"),
  nextEl: document.querySelector(".next"),
  progressEl: document.querySelector(".progress-fill"),
  onSlideChange: ({ index, total }) => console.log(index, total),
  momentumTouch: 0.35, // free-mode (snap:false) coast factor for touch
  momentumMouse: 0.55, // free-mode coast factor for mouse/trackpad
  axisThreshold: 6, // px before gesture commits to X or Y axis
})
<div class="slider">
  <div class="slider__track">
    <div class="slide">01</div>
    <div class="slide">02</div>
    <div class="slide">03</div>
  </div>
</div>

Prev/next buttons auto-disable with -disabled class + aria-disabled at start/end (non-infinite only). Style with .prev.-disabled, .next.-disabled { opacity: 0.3; pointer-events: none; }. Progress bar accounts for visible slides — starts at slidesInView / total, reaches exactly scaleX(1) at the last position. Touch gets 1:1 drag + iOS-style settle; mouse/trackpad keeps damp-based lerp. Set snap: false for free-scroll with momentum.

ScrollTo

import { ScrollTo } from "@linear_non/stellar-libs"

const scrollTo = new ScrollTo({ scope: document })

// On page destroy:
scrollTo.destroy()
<a href="#about" data-scroll-to>About</a>
<button data-scroll-to="top">Back to top</button>
<button data-scroll-to=".contact" data-scroll-to-offset="-80" data-scroll-to-duration="2">Contact</button>

Uses Application.scrollTo() under the hood — works with both internal smooth scroll and Lenis.


Roadmap

  • [ ] TypeScript definitions (.d.ts for all 8 libraries)
  • [ ] Unit test suite (per-library Jest tests)
  • [ ] Accessibility — ARIA attributes + keyboard support (Slider, Marquee, CursorTracker)
  • [ ] Animation presets — exportable GSAP timeline builders per library
  • [ ] Performance monitoring — FPS tracking integrated with stellar-kit ?debug
  • [ ] Storybook interactive docs
  • [ ] Plugin system — .use(plugin) extension API

Lifecycle

All libraries follow a consistent class-based lifecycle: init() → on() → tick() → resize() → off() → destroy()

Always call destroy() on page navigation to clean up event listeners, animations, and timers.


Made with ❤️ by Non-Linear Studio