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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@akitain/sandjs

v0.3.6

Published

Sunburst Advanced Node Data

Readme

Sand.js

Sunburst Advanced Node Data

A lightweight, framework-agnostic JavaScript library for building interactive sunburst charts using SVG. Sand.js is fully data-driven: describe your chart in JSON, and it handles both layout computation and rendering.

npm version GitHub stars

Documentation

View Complete Documentation →

For detailed guides, API reference, and examples, visit the full documentation.


Table of Contents


Introduction

Sand.js is designed for developers who need to visualize hierarchical data as sunburst charts with minimal setup. Built with modern web standards, it offers:

  • Zero dependencies: Lightweight and fast
  • Framework agnostic: Works with vanilla JavaScript or any framework
  • JSON-driven: Declarative configuration
  • Interactive: Built-in tooltips, navigation, and event callbacks
  • Customizable: Extensive theming and styling options
  • TypeScript ready: Full type definitions included

Installation

npm install @akitain/sandjs

For Yarn users:

yarn add @akitain/sandjs

Quick Start

Create a basic sunburst chart in three steps:

  1. Add an SVG element to your HTML:
<svg id="chart"></svg>
  1. Define your data configuration:
import { renderSVG } from '@akitain/sandjs';

const config = {
  size: { radius: 200 },
  layers: [
    {
      id: 'main',
      radialUnits: [0, 2],
      angleMode: 'free',
      tree: [
        { name: 'Engineering', value: 45, key: 'eng' },
        {
          name: 'Design',
          value: 30,
          key: 'design',
          children: [
            { name: 'UI', value: 15 },
            { name: 'UX', value: 15 }
          ]
        },
        { name: 'Marketing', value: 25, key: 'marketing' }
      ]
    }
  ]
};
  1. Render the chart:
const chart = renderSVG({
  el: '#chart',
  config,
  tooltip: true
});

That's it! You now have a fully interactive sunburst chart.


Core Concepts

Understanding these fundamental concepts will help you build complex charts:

Sunburst

The complete chart containing one or more layers. Defined by overall size (radius and optional angle).

Layer

A logical grouping of rings with a shared dataset. Layers can operate independently (free mode) or align with other layers (align mode).

Properties:

  • id (string): Unique identifier
  • radialUnits ([number, number]): Inner and outer radial positions
  • angleMode ('free' | 'align'): How angular space is distributed
  • tree (Node | Node[]): Data structure for the layer

Node

A unit of data representing a segment in your chart. Nodes can have children for hierarchical data.

Key properties:

  • name (string): Display label
  • value (number): Size of the segment
  • key (string, optional): Stable identifier for animations and alignment
  • children (Node[], optional): Child nodes for hierarchical structure

Arc

A computed geometric entity created by the layout engine, ready for rendering with coordinates and metadata.

Ring

A radial band in the chart, automatically calculated based on nodes and their expandLevels property.

Key-group

Nodes sharing the same key value, used for alignment across layers and coordinated interactions.


Configuration Reference

SunburstConfig

The root configuration object for your chart.

{
  size: {
    radius: number;      // Final radius in pixels
    angle?: number;      // Total angle in radians (default: 2π)
  },
  layers: LayerConfig[]  // Array of layer definitions
}

LayerConfig

{
  id: string;                          // Unique layer identifier
  radialUnits: [number, number];       // [inner, outer] radial positions
  angleMode: 'free' | 'align';         // Angular distribution mode
  alignWith?: string;                  // Reference layer ID (for 'align' mode)
  padAngle?: number;                   // Gap between arcs (radians)
  baseOffset?: number;                 // Global rotation offset (radians)
  arcOffsetMode?: 'relative' | 'absolute'; // Offset calculation mode
  defaultArcOffset?: number;           // Default offset for all arcs
  borderColor?: string;                // Border color for arcs in this layer
  borderWidth?: number;                // Border width in pixels
  labelColor?: string;                 // Label text color for this layer
  showLabels?: boolean;                // Show/hide labels for this layer
  tree: TreeNodeInput | TreeNodeInput[]; // Data structure
}

TreeNodeInput

{
  name: string;              // Display name
  value: number;             // Arc size (auto-summed if children exist)
  key?: string;              // Stable identifier
  expandLevels?: number;     // Radial thickness in rings (default: 1)
  offset?: number;           // Local angular offset
  color?: string;            // Custom color (CSS format)
  labelColor?: string;       // Custom label text color
  children?: TreeNodeInput[]; // Child nodes
  tooltip?: string;          // Custom tooltip content
  collapsed?: boolean;       // Hide children while preserving value
  hidden?: boolean;          // Hide node completely
}

Features

Color Themes

Sand.js includes 14 built-in color palettes across three theme types.

Qualitative Themes

Best for categorical data with no inherent order:

import { renderSVG, QUALITATIVE_PALETTES } from '@akitain/sandjs';

renderSVG({
  el: '#chart',
  config,
  colorTheme: {
    type: 'qualitative',
    palette: 'ocean',  // 'default' | 'pastel' | 'vibrant' | 'earth' | 'ocean' | 'sunset'
    assignBy: 'key'    // Color assignment strategy
  }
});

Sequential Themes

Best for ordered data with progression from low to high:

colorTheme: {
  type: 'sequential',
  palette: 'blues',  // 'blues' | 'greens' | 'purples' | 'oranges'
  assignBy: 'depth'
}

Diverging Themes

Best for data with a meaningful midpoint (e.g., positive/negative values):

colorTheme: {
  type: 'diverging',
  palette: 'redBlue',  // 'redBlue' | 'orangePurple' | 'greenRed'
  assignBy: 'value'
}

Color Assignment Strategies

  • key: Consistent colors based on arc keys (default for qualitative)
  • depth: Colors vary by hierarchical depth (default for sequential/diverging)
  • index: Sequential assignment by arc position
  • value: Colors mapped to normalized values

Custom Palettes

colorTheme: {
  type: 'qualitative',
  palette: ['#ff6b6b', '#4ecdc4', '#45b7d1', '#f7dc6f'],
  assignBy: 'key'
}

Custom Color Keys

colorTheme: {
  type: 'qualitative',
  palette: 'default',
  deriveKey: (arc) => arc.data.category  // Use any arc property
}

Note: Individual node.color values always override theme colors.


Navigation & Drilldown

Enable interactive drill-down navigation with smooth transitions:

Basic Usage

const chart = renderSVG({
  el: '#chart',
  config,
  navigation: true,  // Enable with defaults
  transition: true   // Enable smooth animations
});

Advanced Options

navigation: {
  layers: ['main', 'details'],  // Specify navigable layers
  rootLabel: 'Home',            // Breadcrumb root text
  focusTransition: {
    duration: 600,               // Animation duration (ms)
    easing: (t) => t * t        // Custom easing function
  },
  onFocusChange: (focus) => {
    if (focus) {
      console.log('Focused:', focus.arc.data.name);
    } else {
      console.log('Reset to root');
    }
  }
}

Programmatic Control

// Reset to root view
chart.resetNavigation?.();

Tooltips

Display contextual information on hover.

Basic Tooltips

renderSVG({
  el: '#chart',
  config,
  tooltip: true  // Enable default tooltips
});

Custom Tooltips

tooltip: {
  formatter: (arc) => {
    return `
      <strong>${arc.data.name}</strong><br>
      Value: ${arc.data.value}<br>
      Percentage: ${arc.percentage.toFixed(1)}%
    `;
  },
  container: '#tooltip-container'  // Custom container selector
}

Per-Node Tooltips

tree: [
  {
    name: 'Engineering',
    value: 45,
    tooltip: 'Custom tooltip for Engineering department'
  }
]

Breadcrumbs

Visualize the current navigation path.

Basic Breadcrumbs

renderSVG({
  el: '#chart',
  config,
  breadcrumbs: true  // Enable with defaults
});

Advanced Configuration

breadcrumbs: {
  container: '#breadcrumb-trail',  // Custom container
  interactive: true,               // Enable click navigation
  separator: ' › ',                // Custom separator
  rootLabel: 'Overview',           // Root element label
  formatter: (arc) => arc.data.name.toUpperCase()  // Custom formatting
}

Highlighting

Highlight related arcs by key.

Basic Highlighting

renderSVG({
  el: '#chart',
  config,
  highlightByKey: true  // Enable with defaults
});

Advanced Options

highlightByKey: {
  className: 'highlighted',  // Custom CSS class
  pinOnClick: true,          // Keep highlight on click
  onPinChange: (key, pinned) => {
    console.log(`${key} is ${pinned ? 'pinned' : 'unpinned'}`);
  }
}

Transitions

Smooth animations when updating your chart.

Enable Transitions

renderSVG({
  el: '#chart',
  config,
  transition: true  // Enable with defaults
});

Custom Transition Settings

transition: {
  duration: 800,           // Animation duration (ms)
  easing: (t) => t * t,   // Easing function
  delay: 100              // Delay before animation starts (ms)
}

Updating with Transitions

const chart = renderSVG({ el: '#chart', config, transition: true });

// Later, update with smooth transition
chart.update({
  config: newConfig,
  transition: {
    duration: 500
  }
});

Labels

Render text labels on arcs.

Enable Labels

renderSVG({
  el: '#chart',
  config,
  labels: true  // Enable default labels
});

Custom Label Formatting

labels: {
  formatter: (arc) => {
    if (arc.percentage > 10) {
      return `${arc.data.name} (${arc.percentage.toFixed(0)}%)`;
    }
    return '';  // Hide labels for small arcs
  }
}

Note: Labels automatically hide on arcs that are too narrow to display text legibly.


API Reference

renderSVG(options)

Main function to create a sunburst chart.

Parameters:

{
  el: string | SVGElement;           // Target SVG element or selector
  config: SunburstConfig;            // Chart configuration
  tooltip?: boolean | TooltipOptions; // Tooltip settings
  breadcrumbs?: boolean | BreadcrumbOptions; // Breadcrumb settings
  highlightByKey?: boolean | HighlightByKeyOptions; // Highlight settings
  navigation?: boolean | NavigationOptions; // Navigation settings
  transition?: boolean | TransitionOptions; // Transition settings
  labels?: boolean | LabelOptions;   // Label settings
  colorTheme?: ColorThemeOptions;    // Color theme
  onArcEnter?: (payload) => void;    // Hover enter callback
  onArcMove?: (payload) => void;     // Hover move callback
  onArcLeave?: (payload) => void;    // Hover leave callback
  onArcClick?: (payload) => void;    // Click callback
  debug?: boolean;                   // Enable diagnostic logging
}

Returns:

{
  update: (updateInput) => void;     // Update the chart
  dispose: () => void;               // Clean up resources
  resetNavigation?: () => void;      // Reset to root (if navigation enabled)
}

layout(config)

Compute arc geometries from configuration (layout-only mode).

Parameters:

  • config (SunburstConfig): Chart configuration

Returns:

  • LayoutArc[]: Array of computed arcs with geometry and metadata

formatArcBreadcrumb(arc)

Generate a breadcrumb trail for an arc.

Parameters:

  • arc (LayoutArc): The arc to generate breadcrumbs for

Returns:

  • BreadcrumbTrailItem[]: Array of breadcrumb items

Build & Development

Development Setup

# Clone the repository
git clone https://github.com/aqu1tain/sandjs.git
cd sandjs

# Install dependencies
npm install

# Run tests
npm test

# Build the library
npm run build

# Run tests and build
npm run verify

Development Server

npm run dev

Opens a development server at http://localhost:4173 with live examples.

Project Structure

sandjs/
├── src/
│   ├── index.ts           # Public API exports
│   ├── layout/            # Layout computation
│   ├── render/            # SVG rendering
│   └── types/             # TypeScript definitions
├── demo/                  # Interactive examples
├── dist/                  # Build output (generated)
└── tests/                 # Test suite

Build Output

  • dist/sandjs.mjs: ES Module (default)
  • dist/sandjs.iife.min.js: Minified IIFE for CDN usage
  • dist/index.d.ts: TypeScript type definitions

CDN Usage

For quick prototyping or non-bundled environments:

<svg id="chart"></svg>

<script src="https://unpkg.com/@akitain/[email protected]/dist/sandjs.iife.min.js"></script>
<script>
  const { renderSVG } = window.SandJS;

  renderSVG({
    el: '#chart',
    config: {
      size: { radius: 200 },
      layers: [
        {
          id: 'main',
          radialUnits: [0, 2],
          angleMode: 'free',
          tree: [
            { name: 'Category A', value: 40 },
            { name: 'Category B', value: 60 }
          ]
        }
      ]
    },
    tooltip: true
  });
</script>

License

MIT © Aqu1tain