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

@zero.sc/motion

v0.2.0

Published

Physics-modelled motion for React with zero runtime dependencies — refraction, Fresnel specular, volume-preserving soft bodies, Verlet cloth, ferrofluid, metaballs, rack focus, caustics and velocity-preserving handoff. Reduced-motion respected everywhere.

Readme


Why springs

A CSS easing curve finishes when its clock runs out. If the user changes their mind halfway, the curve keeps its own schedule anyway. A spring carries velocity instead of a duration, so when the target moves it continues from wherever it currently is. That is where "follows your hand" comes from.

Those curves are what this package's own solver produced — not hand-drawn. springStep was run at 8 ms intervals to sample the coordinates, and bouncy's peak of 1.15 is a computed result.

Install

npm install @zero.sc/motion
# pnpm add @zero.sc/motion  ·  yarn add @zero.sc/motion

react and react-dom 19 are peers. Nothing else comes along.

Sixty seconds

import { Reveal, Stagger, usePresence } from '@zero.sc/motion';

// 1 — appear once, when it enters the viewport
export function Hero() {
  return (
    <Reveal>
      <h1>Zero</h1>
    </Reveal>
  );
}

// 2 — lists arrive in sequence; the gap token carries its own ceiling
export function List({ items }: { items: string[] }) {
  return (
    <Stagger>
      {items.map((it) => (
        <li key={it}>{it}</li>
      ))}
    </Stagger>
  );
}

// 3 — stay mounted until the exit animation has actually finished
export function Sheet({ open }: { open: boolean }) {
  const { mounted, state, ref } = usePresence(open);
  if (!mounted) return null;
  return (
    <div ref={ref} data-state={state}>
      sheet
    </div>
  );
}

Five spring tokens

Pick a situation, not a number. These curves are integrated results too.

| Token | When | Character | |-------|------|-----------| | snappy | Cursors and drags — anything that must track a hand | Settles first | | default | Most things | Firm, no overshoot | | gentle | Sheets and panels — large surfaces | Unhurried | | bouncy | Small elements saying "I'm alive" | Overshoots to 1.15, then sits down | | heavy | Modal scrims — things that should carry inertia | Weighted |

import { useSpringStyle } from '@zero.sc/motion';

const ref = useSpringStyle<HTMLDivElement>(isOpen ? 1 : 0, {
  config: 'snappy',
  render: (value, node) => {
    node.style.transform = `scale(${value})`;
  },
});

render touches the DOM directly, inside rAF. It does not re-render on every value change — a number running at 60 fps that shakes the React tree eats the frame budget it was trying to protect.

What's inside

The spring solver · Presence (stays through exit) · Reveal (viewport entry) · Stagger (sequence) · useFlip (FLIP position transitions) · a View Transitions wrapper · pointer reactions like Magnetic, Tilt and Ripple · text effects like SplitText, Typewriter and CountUp131 exports.

Reduced motion is not an option flag

For a user who has turned on prefers-reduced-motion: reduce, every translation, scale and rotation is switched off. Not everything disappears — opacity transitions remain, because a state change still has to be visible. That decision lives in one place, motion-mode, rather than in each component, and an app can force it with setMotionOverride.

import { useReducedMotion, useShouldAnimate } from '@zero.sc/motion';

const reduced = useReducedMotion();      // the system setting
const animate = useShouldAnimate();      // system + app override, resolved

Honest limits

  • Layout animation stops at FLIP. There is no automatic layout tracking — you tell useFlip when to measure.
  • No SVG path morphing. Morph transitions between rectangles; it does not interpolate paths.
  • This is 0.x. Semver makes no promises here, and the export surface may shrink before 1.0.
  • The license text shipped with this version is still an unreviewed draft — see below.

Around it

| | | |---|---| | Docs and playground | kit.zero.sc | | Components | @zero.sc/ui — built on this | | Everything | @zero.sc |

License

MIT OR Zero License v1.0 — take whichever you prefer. Choosing MIT is enough; nothing further is required of you.

The Zero name, marks and logos are not covered — build anything you like with this code, just don't present it as a Zero product.

Copyright (c) 2026 Zero. Source Code begins at Zero.