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

@tripp-horbinski/sportviz

v0.2.1

Published

Composable sports data visualization for React — basketball courts, shot charts, hexbin heatmaps, zone efficiency, play animations

Readme

sportviz

Composable sports data visualization for React. NBA court surfaces with scatter, hexbin, zone, annotation, and play animation overlays.

Install

npm install @tripp-horbinski/sportviz

Quick Start

import { BasketballCourt, ScatterOverlay } from "@tripp-horbinski/sportviz";

const shots = [
  { x: 0, y: 1, made: true },
  { x: -5, y: 15, made: false },
  { x: 22, y: 3, made: true },
];

function ShotChart() {
  return (
    <BasketballCourt theme="dark" orientation="half">
      <ScatterOverlay
        data={shots}
        radius={0.4}
        color={(p) => (p.made ? "#22c55e" : "#ef4444")}
      />
    </BasketballCourt>
  );
}

Overlays

Scatter

Individual data points on the court.

<ScatterOverlay
  data={shots}
  radius={0.4}
  color={(p) => (p.made ? "#22c55e" : "#ef4444")}
  opacity={0.75}
  onPointHover={(point, e) => console.log(point)}
  onPointClick={(point, e) => console.log(point)}
/>

Hexbin

Aggregate data into hexagonal bins with color-coded frequency.

import { blueRed } from "@tripp-horbinski/sportviz";

<HexbinOverlay
  data={shots}
  radius={1.8}
  colorScale={blueRed}
  onCellHover={(cell, e) => console.log(cell?.count)}
/>

Zones

NBA shooting zones with computed efficiency stats.

import { redGreen } from "@tripp-horbinski/sportviz";

<ZoneOverlay
  data={shots}
  stat="made"
  colorScale={redGreen}
  opacity={0.5}
  onZoneHover={(zone, e) => console.log(zone?.label, zone?.value)}
/>

Annotations

Labels, markers, and arrows on the court.

<AnnotationOverlay
  annotations={[
    { x: 0, y: 1.5, label: "Rim", mark: "ring", color: "#22c55e" },
    { x: -22, y: 1, label: "L Corner", mark: "dot", color: "#f59e0b" },
    { x: 10, y: 15, label: "Spot", mark: "cross", target: { x: 0, y: 0 } },
  ]}
/>

Play Animation

Animated play sequences with ball trail and player movement.

const play: PlaySequence = {
  duration: 3,
  frames: [
    {
      time: 0,
      ball: { x: 0, y: 25 },
      players: [
        { id: "1", label: "PG", x: 0, y: 25, color: "#3b82f6" },
        { id: "2", label: "C", x: 5, y: 15, color: "#3b82f6" },
      ],
    },
    {
      time: 1,
      ball: { x: 0, y: 2 },
      players: [
        { id: "1", label: "PG", x: -8, y: 10, color: "#3b82f6" },
        { id: "2", label: "C", x: 0, y: 2, color: "#3b82f6" },
      ],
    },
  ],
};

<PlayOverlay sequence={play} progress={0.5} />

Court Options

<BasketballCourt
  theme="dark"              // "light" | "dark" | "lakers" | "celtics" | ... (30 NBA teams)
  orientation="half"        // "half" | "full"
  centerLogo="/logo.png"    // optional center court image
  centerLogoSize={10}       // logo size in court units (feet)
/>

Team Themes

All 30 NBA teams available as themes. Wood-toned court with team colors on paint and lines.

<BasketballCourt theme="warriors" />  // blue paint, gold lines
<BasketballCourt theme="lakers" />    // purple paint, gold lines
<BasketballCourt theme="celtics" />   // green paint, white lines

Map team abbreviations to theme names:

import { teamThemeMap } from "@tripp-horbinski/sportviz";

const theme = teamThemeMap["GSW"]; // "warriors"

Coordinate System

Origin at basket center, units in feet. +X is right, +Y is toward halfcourt.

  • Basket: (0, 0)
  • Free throw line: (0, 13.75)
  • Three-point arc: radius 23.75 from origin
  • Corner three: (±22, -5.25) to (±22, 8.75)

NBA API coordinates (LOC_X, LOC_Y) convert by dividing by 10.

Color Scales

import { blueRed, redGreen, greenRed, colorScale } from "@tripp-horbinski/sportviz";

// Built-in
blueRed    // cold → hot (frequency)
redGreen   // bad → good (efficiency like FG%)
greenRed   // good → bad

// Custom
const custom = colorScale(["#000000", "#ff0000", "#ffff00"]);

Package

@tripp-horbinski/sportviz — React components + framework-agnostic core bundled together. Single install, single import.

Development

# Install
bun install

# Build packages
cd packages/core && bun run build
cd packages/react && bun run build

# Run demo
cd apps/demo && bunx vite

# Test
cd packages/core && bun test

License

MIT