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

react-native-ballast-charts

v1.0.0

Published

High-performance interactive charts for React Native with advanced gap handling and financial data visualization

Readme

React Native Ballast Charts

A high-performance, interactive chart library for React Native with advanced gap handling and financial data visualization.

npm version npm downloads TypeScript React Native License: MIT

Features

  • 📊 Interactive Charts: Touch-responsive charts with crosshair and tooltip support
  • 🎯 High Performance: Optimized for 60fps with React Native Reanimated worklets
  • 📈 Smooth Curves: Multiple smoothing algorithms (Bézier, Catmull-Rom, Cardinal)
  • ⏸️ Advanced Gap Handling: Both proportional and fixed-width gap visualization
  • 🎨 Customizable Styling: Comprehensive theming and styling options
  • 📱 React Native Optimized: Built specifically for mobile performance

Screenshots

| Line Chart | Distribution Chart | |------------|-------------------| | Line Chart | Distribution Chart | | Interactive stock price chart with smooth curves and gap handling | Distribution visualization with optimized padding |

Installation

npm install react-native-ballast-charts

Peer Dependencies

This library requires the following peer dependencies:

npm install react-native-reanimated react-native-gesture-handler react-native-svg

Follow the installation guides for each:

Quick Start

import { Chart } from 'react-native-ballast-charts';

const MyChart = () => {
  const data = {
    x: [1640995200000, 1641081600000, 1641168000000], // timestamps
    y: [100, 120, 110] // values
  };

  return (
    <Chart
      data={data}
      width={300}
      height={200}
      lineStyle={{
        color: '#007AFF',
        width: 2,
        smoothing: 'bezier'
      }}
    />
  );
};

Gap Handling

This library provides sophisticated gap handling for time series data with missing periods.

Gap Detection

Gaps are automatically detected when the time interval between consecutive data points exceeds a threshold:

<Chart
  data={data}
  gaps={{
    enabled: true,
    threshold: 2.5 // Gap detected when interval > 2.5x median interval
  }}
/>

Proportional Gaps (Default)

By default, gaps are rendered proportionally to their time duration:

<Chart
  data={data}
  gaps={{
    enabled: true,
    threshold: 2.5,
    style: {
      color: '#999',
      width: 1,
      dashArray: '4 4'
    }
  }}
/>

Behavior: A 1-week gap will appear larger than a 1-day gap, proportional to their time difference.

Fixed Width Gaps

For consistent visual representation regardless of gap duration:

<Chart
  data={data}
  gaps={{
    enabled: true,
    threshold: 2.5,
    fixedWidthGaps: true,
    fixedWidth: 40, // All gaps appear as exactly 40px
    style: {
      color: '#999',
      width: 1,
      dashArray: '2 3'
    }
  }}
/>

Behavior: All gaps appear as the same visual width (40px by default), regardless of their actual time duration.

How Fixed Width Gaps Work

  1. Gap Detection: Identifies time periods where data is missing
  2. Segment Division: Divides the timeline into continuous data segments separated by gaps
  3. Consistent Scaling: Applies uniform time-to-pixel scaling across all segments
  4. Fixed Gap Insertion: Inserts exactly fixedWidth pixels between segments

Example: With a 1-week dataset containing weekend gaps:

  • Proportional: Weekend gaps appear larger than weekday gaps
  • Fixed Width: All gaps appear identical (e.g., 40px), maintaining visual consistency

When to Use Fixed Width Gaps

  • Financial Charts: Trading hours vs. market closures
  • Business Metrics: Weekdays vs. weekends
  • Sensor Data: Regular maintenance periods
  • Any scenario where gap duration shouldn't distort visual analysis

Gap Configuration Options

interface GapConfig {
  enabled: boolean;                    // Enable gap detection
  threshold?: number;                  // Gap threshold multiplier (default: 2.0)
  fixedWidthGaps?: boolean;           // Use fixed width gaps
  fixedWidth?: number;                // Fixed gap width in pixels (default: 40)
  style?: {
    color?: string;                   // Gap indicator color
    width?: number;                   // Gap indicator line width
    dashArray?: string;               // Dash pattern (e.g., "4 4", "2 3")
  };
}

Chart Props

Core Props

interface ChartProps {
  data: ChartData;                    // Chart data
  width: number;                      // Chart width
  height: number;                     // Chart height
  padding?: Padding;                  // Chart padding
  style?: ViewStyle;                  // Container styling
}

interface ChartData {
  x: number[];                        // X-axis data (usually timestamps)
  y: number[];                        // Y-axis data (values)
}

Styling Props

interface LineStyle {
  color?: string;                     // Line color
  width?: number;                     // Line width
  opacity?: number;                   // Line opacity
  smoothing?: 'none' | 'bezier' | 'catmull-rom' | 'cardinal';
  tension?: number;                   // Curve tension (0-1)
}

interface FillStyle {
  enabled?: boolean;                  // Enable area fill
  color?: string;                     // Fill color
  opacity?: number;                   // Fill opacity
}

Interaction Props

interface InteractionConfig {
  enabled?: boolean;                  // Enable touch interactions
  onDrag?: (x: number, y: number, index: number) => void;
  onDragStart?: (x: number, y: number, index: number) => void;
  onDragEnd?: (x: number, y: number, index: number) => void;
  onTap?: (x: number, y: number, index: number) => void;
  dragLineStyle?: LineStyle;          // Crosshair styling
}

Complete Example

<Chart
  data={{ x: timestamps, y: prices }}
  width={350}
  height={200}
  padding={{ top: 20, right: 20, bottom: 40, left: 60 }}
  
  lineStyle={{
    color: '#007AFF',
    width: 2,
    opacity: 1,
    smoothing: 'bezier',
    tension: 0.3
  }}
  
  fillStyle={{
    enabled: true,
    color: '#007AFF',
    opacity: 0.1
  }}
  
  gaps={{
    enabled: true,
    threshold: 2.5,
    fixedWidthGaps: true,
    fixedWidth: 40,
    style: {
      color: '#999',
      width: 1,
      dashArray: '2 3'
    }
  }}
  
  interaction={{
    enabled: true,
    onDrag: (x, y, index) => {
      console.log('Dragging:', { x, y, index });
    },
    dragLineStyle: {
      color: '#FF3B30',
      width: 1,
      opacity: 0.8
    }
  }}
  
  axes={{
    x: {
      show: true,
      style: { lineColor: '#E5E5E7', labelStyle: { color: '#8E8E93' } }
    },
    y: {
      show: true,
      style: { lineColor: '#E5E5E7', labelStyle: { color: '#8E8E93' } }
    }
  }}
/>

Performance Considerations

  • Worklet Optimization: Touch interactions run on the UI thread for 60fps performance
  • Data Scaling: Coordinate calculations are memoized and optimized
  • SVG Rendering: Efficient path generation with minimal DOM updates
  • Memory Management: Automatic cleanup of gesture handlers and animations

TypeScript Support

The library is fully typed with comprehensive TypeScript definitions. All props, configs, and callback signatures include complete type information.

Migration Notes

From Proportional to Fixed Width Gaps

// Before (proportional gaps)
gaps={{ enabled: true, threshold: 2.5 }}

// After (fixed width gaps)
gaps={{ 
  enabled: true, 
  threshold: 2.5,
  fixedWidthGaps: true,
  fixedWidth: 40 
}}

Breaking Changes

None. Fixed width gaps are an additive feature that doesn't affect existing implementations.

Troubleshooting

Gaps Not Appearing

  • Verify gaps.enabled: true
  • Check that threshold value is appropriate for your data intervals
  • Ensure data actually contains time gaps (missing periods)

Unexpected Gap Sizes

  • Proportional gaps: Gap size reflects actual time duration
  • Fixed width gaps: All gaps appear as fixedWidth pixels regardless of duration

Performance Issues

  • Reduce data point density for large datasets
  • Consider data downsampling for initial render
  • Use React.memo for chart container components

Contributing

This library is part of the Ballast investment application. For contributions or issues, please follow the project's standard development workflow.