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

@nandkapadia/lightweight-charts-pro-core

v0.1.1

Published

Framework-agnostic core library for TradingView Lightweight Charts Pro

Downloads

5

Readme

@nandkapadia/lightweight-charts-pro-core

npm version License: MIT TypeScript CI/CD

Framework-agnostic TypeScript library for TradingView Lightweight Charts with advanced custom series, primitives, and utilities.

🚀 Features

  • Custom Series Plugins: Band, Ribbon, Gradient Ribbon, Signal, and Trend Fill series
  • UI Primitives: Legend, Range Switcher, and Trade Rectangle overlays
  • Services: Chart coordinate management, layout management, template engine
  • Comprehensive Type Definitions: Full TypeScript support with 100% documented APIs
  • Framework Agnostic: Use with React, Vue, Streamlit, or vanilla JavaScript
  • Tree-Shakeable: Modular exports for optimal bundle sizes
  • Production Ready: Zero dependencies (except peer dependency on lightweight-charts)

📦 Installation

npm install @nandkapadia/lightweight-charts-pro-core lightweight-charts
yarn add @nandkapadia/lightweight-charts-pro-core lightweight-charts
pnpm add @nandkapadia/lightweight-charts-pro-core lightweight-charts

🎯 Quick Start

Basic Usage

import { createChart } from 'lightweight-charts';
import { createBandSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';

const chart = createChart(document.getElementById('chart'));
const bandSeries = createBandSeries(chart, {
  upperLineColor: '#26a69a',
  lowerLineColor: '#ef5350',
  fillColor: 'rgba(38, 166, 154, 0.2)',
});

bandSeries.setData([
  { time: '2024-01-01', upper: 105, lower: 95 },
  { time: '2024-01-02', upper: 108, lower: 92 },
  // ...
]);

Using Primitives

import { LegendPrimitive } from '@nandkapadia/lightweight-charts-pro-core/primitives';

const legend = new LegendPrimitive({
  text: 'My Series',
  position: 'top-left',
});

series.attachPrimitive(legend);

Using Services

import { ChartCoordinateService } from '@nandkapadia/lightweight-charts-pro-core/services';

const coordService = ChartCoordinateService.getInstance();
const dimensions = await coordService.getValidatedChartDimensions(chart, container);

⏰ Time and Timezone Handling

IMPORTANT: This library does NOT perform any timezone conversions. All time values are treated as opaque.

Philosophy

The library follows a strict "no timezone conversion" policy:

  • Backend Responsibility: Your backend/server is responsible for all timezone handling
  • Opaque Values: The library treats all time values as-is without modification
  • User Control: You have full control over how times are interpreted and displayed

Supported Time Formats

The library accepts and normalizes various time formats WITHOUT conversion:

// Unix timestamp (seconds) - recommended
{ time: 1705312800, value: 100 }

// ISO 8601 string - treated as-is
{ time: '2024-01-15T10:00:00.000Z', value: 100 }

// ISO with timezone offset - preserved
{ time: '2024-01-15T10:00:00.000+05:00', value: 100 }

// BusinessDay format - midnight UTC
{ time: { year: 2024, month: 1, day: 15 }, value: 100 }

// Numeric string
{ time: '1705312800', value: 100 }

Best Practices

1. Use Unix Timestamps (Recommended)

// Backend sends Unix timestamps in seconds
const data = [
  { time: 1705312800, value: 100 }, // 2024-01-15 10:00:00 UTC
  { time: 1705316400, value: 105 }, // 2024-01-15 11:00:00 UTC
];

2. Backend Handles Timezone Conversion

# Python backend example
from datetime import datetime
import pytz

# User's timezone
user_tz = pytz.timezone('America/New_York')

# Convert to user's timezone BEFORE sending to frontend
dt = datetime(2024, 1, 15, 10, 0, 0, tzinfo=pytz.UTC)
user_dt = dt.astimezone(user_tz)

# Send as Unix timestamp
timestamp = int(user_dt.timestamp())  # Already in user's timezone

3. Display Formatting (Optional)

If you need to display times in a specific timezone, use custom formatters:

import { TemplateEngine } from '@nandkapadia/lightweight-charts-pro-core/services';

const engine = TemplateEngine.getInstance();

// Default: ISO 8601 UTC (no conversion)
const result = engine.processTemplate(
  'Time: $$time$$',
  { seriesData: { time: 1705312800 } }
);
// Result: "Time: 2024-01-15T10:00:00.000Z"

// Custom: Display in specific timezone
const resultWithTz = engine.processTemplate(
  'Time: $$time$$',
  { seriesData: { time: 1705312800 } },
  {
    timeFormatter: (timestamp) => {
      const date = new Date(timestamp * 1000);
      return date.toLocaleString('en-US', {
        timeZone: 'America/New_York',
        dateStyle: 'short',
        timeStyle: 'short'
      });
    }
  }
);
// Result: "Time: 1/15/24, 5:00 AM" (EST)

What This Library Does

Normalizes different time formats to Unix timestamps (seconds) ✅ Preserves timezone information in ISO strings ✅ Formats times as ISO 8601 UTC by default ✅ Provides optional custom formatters for display ✅ Optimizes time operations with binary search (O(log n))

What This Library Does NOT Do

Does NOT convert times between timezones ❌ Does NOT apply local browser timezone ❌ Does NOT assume any timezone ❌ Does NOT modify your time data

Migration Guide

If you were relying on automatic timezone conversion:

Before (❌ Don't do this):

// Frontend expecting automatic conversion
const data = [
  { time: '2024-01-15T10:00:00Z', value: 100 }
];
// OLD: Would convert to browser timezone

After (✅ Do this):

// Backend converts to target timezone
// Python example:
// user_tz = pytz.timezone('America/New_York')
// timestamp = int(dt.astimezone(user_tz).timestamp())

const data = [
  { time: 1705329600, value: 100 } // Already in user's timezone
];

Time Utilities

The library provides utilities for working with times:

import {
  normalizeTime,
  formatTime,
  findNearestTimestamp,
  createSortedTimeArray
} from '@nandkapadia/lightweight-charts-pro-core/utils';

// Normalize any time format (no conversion)
const timestamp = normalizeTime('2024-01-15T10:00:00.000Z');
// Returns: 1705312800

// Format timestamp (ISO 8601 UTC by default)
const formatted = formatTime(1705312800);
// Returns: "2024-01-15T10:00:00.000Z"

// Find nearest timestamp (O(log n) binary search)
const sorted = createSortedTimeArray([1000, 2000, 3000, 4000, 5000]);
const nearest = findNearestTimestamp(2400, sorted);
// Returns: 2000 (closest match)

📚 Documentation

Custom Series

Band Series

Display data with upper and lower bounds (e.g., Bollinger Bands).

import { createBandSeries, BandData } from '@nandkapadia/lightweight-charts-pro-core/plugins';

const data: BandData[] = [
  { time: '2024-01-01', upper: 105, lower: 95 },
  { time: '2024-01-02', upper: 108, lower: 92 },
];

const bandSeries = createBandSeries(chart, {
  upperLineColor: '#26a69a',
  lowerLineColor: '#ef5350',
  fillColor: 'rgba(38, 166, 154, 0.2)',
});

bandSeries.setData(data);

Ribbon Series

Multiple moving averages displayed as a ribbon.

import { createRibbonSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';

const ribbonSeries = createRibbonSeries(chart, {
  fillColor: '#2196F3',
  opacity: 0.3,
});

Signal Series

Binary or numeric signals displayed as colored backgrounds.

import { createSignalSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';

const signalSeries = createSignalSeries(chart, {
  signalColor: '#4CAF50',
  neutralColor: 'transparent',
  alertColor: '#f44336',
});

signalSeries.setData([
  { time: '2024-01-01', value: 1 },  // Buy signal
  { time: '2024-01-02', value: 0 },  // Neutral
  { time: '2024-01-03', value: -1 }, // Sell signal
]);

Unified Series Factory

Descriptor-based series creation with consistent API:

import { SeriesFactory } from '@nandkapadia/lightweight-charts-pro-core/series';

const factory = new SeriesFactory();

// Create any series type
const series = factory.createSeries(chart, {
  type: 'band',
  data: bandData,
  options: {
    upperLineColor: '#26a69a',
    lowerLineColor: '#ef5350',
  },
});

// Get available series types
const types = factory.getAvailableSeriesTypes();
// ['line', 'area', 'candlestick', 'bar', 'histogram', 'baseline', 'band', 'ribbon', ...]

// Check if custom series
const isCustom = factory.isCustomSeries('band'); // true

Primitives

Legend Primitive

Customizable chart legend with template support:

import { createLegendPrimitive, DefaultLegendConfigs } from '@nandkapadia/lightweight-charts-pro-core/primitives';

const legend = createLegendPrimitive({
  ...DefaultLegendConfigs.default,
  text: 'AAPL',
  position: 'top-left',
});

series.attachPrimitive(legend);

Range Switcher Primitive

Time range selector buttons:

import { createRangeSwitcherPrimitive } from '@nandkapadia/lightweight-charts-pro-core/primitives';

const rangeSwitcher = createRangeSwitcherPrimitive({
  ranges: [
    { label: '1D', range: TimeRange.ONE_DAY },
    { label: '1W', range: TimeRange.ONE_WEEK },
    { label: '1M', range: TimeRange.ONE_MONTH },
  ],
  position: 'bottom-right',
});

chart.attachPrimitive(rangeSwitcher);

Services

ChartCoordinateService

Singleton service for chart coordinate management:

import { ChartCoordinateService } from '@nandkapadia/lightweight-charts-pro-core/services';

const service = ChartCoordinateService.getInstance();

// Get validated dimensions
const dimensions = await service.getValidatedChartDimensions(chart, container, {
  minWidth: 400,
  minHeight: 300,
});

// Get pane coordinates
const paneCoords = service.getPaneCoordinates(chart, 0);

TemplateEngine

String template interpolation for dynamic content:

import { TemplateEngine } from '@nandkapadia/lightweight-charts-pro-core/services';

const engine = new TemplateEngine();
const result = engine.process('Price: {{price}}', { price: 123.45 });
// Result: "Price: 123.45"

🏗️ Architecture

The library is organized into 6 main modules:

1. Plugins (/plugins)

Custom series and chart plugins:

  • bandSeriesPlugin - Band series with upper/lower bounds
  • ribbonSeriesPlugin - Multi-line ribbon visualization
  • gradientRibbonSeriesPlugin - Ribbon with gradient coloring
  • signalSeriesPlugin - Binary/numeric signal visualization
  • trendFillSeriesPlugin - Trend-following fill areas
  • tooltipPlugin - Interactive chart tooltips
  • rectanglePlugin - Rectangle overlay plugin

2. Primitives (/primitives)

UI primitive components for chart overlays:

  • BasePanePrimitive - Base class for pane primitives
  • BaseSeriesPrimitive - Base class for series primitives
  • LegendPrimitive - Chart legend component
  • RangeSwitcherPrimitive - Time range selector
  • TradeRectanglePrimitive - Trade visualization rectangles

3. Series (/series)

Unified series factory with descriptor pattern:

  • UnifiedSeriesFactory - Main factory for series creation
  • UnifiedSeriesDescriptor - Descriptor pattern for series config
  • UnifiedPropertyMapper - Property mapping utilities
  • Built-in and custom series descriptors

4. Services (/services)

Chart management services:

  • ChartCoordinateService - Coordinate system management (singleton)
  • CornerLayoutManager - UI element positioning
  • PrimitiveEventManager - Event handling for primitives
  • TemplateEngine - String template interpolation
  • TradeTemplateProcessor - Trade data template processing

5. Utils (/utils)

Shared utility functions:

  • Logging: logger, chartLog, primitiveLog, perfLog
  • Patterns: SingletonBase, KeyedSingletonManager
  • Performance: throttle, memoize, batchDOMUpdates
  • Validation: coordinateValidation, dataValidation
  • Color: colorUtils, signalColorUtils

6. Types (/types)

TypeScript type definitions for all modules.

🛠️ Development

Prerequisites

  • Node.js 18.x or 20.x
  • npm, yarn, or pnpm

Setup

# Clone the repository
git clone https://github.com/nandkapadia/lightweight-charts-pro-frontend.git
cd lightweight-charts-pro-frontend

# Install dependencies
npm install

# Build the library
npm run build

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Type check
npm run type-check

# Lint
npm run lint

# Format code
npm run format

Build Output

The build produces:

  • ESM: dist/index.js (ES modules)
  • CJS: dist/index.cjs (CommonJS)
  • Types: dist/index.d.ts (TypeScript declarations)

Separate entry points for tree-shaking:

  • dist/plugins/index.js
  • dist/primitives/index.js
  • dist/series/index.js
  • dist/services/index.js
  • dist/utils/index.js

📖 API Reference

Exports

// Main entry point
import { ... } from '@nandkapadia/lightweight-charts-pro-core';

// Module-specific imports (tree-shakeable)
import { createBandSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';
import { LegendPrimitive } from '@nandkapadia/lightweight-charts-pro-core/primitives';
import { SeriesFactory } from '@nandkapadia/lightweight-charts-pro-core/series';
import { ChartCoordinateService } from '@nandkapadia/lightweight-charts-pro-core/services';
import { logger } from '@nandkapadia/lightweight-charts-pro-core/utils';

Type Definitions

All exports include comprehensive TypeScript type definitions:

import type {
  BandData,
  BandSeriesOptions,
  RibbonData,
  SignalData,
  ExtendedChartApi,
  ExtendedSeriesApi,
} from '@nandkapadia/lightweight-charts-pro-core';

🤝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for details.

Development Workflow

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Code Style

  • Follow TypeScript best practices
  • Use Google-style JSDoc comments
  • Ensure all tests pass
  • Maintain 100% type safety
  • Run npm run lint and npm run format before committing

📄 License

MIT License - see LICENSE file for details.

🙏 Acknowledgments

📞 Support

🗺️ Roadmap

  • [ ] Additional custom series types
  • [ ] More UI primitives (volume profile, heatmaps)
  • [ ] Enhanced template engine with more formatters
  • [ ] Performance optimizations for large datasets
  • [ ] Framework-specific examples (React, Vue, Svelte)
  • [ ] Comprehensive documentation site

Made with ❤️ for the trading and financial charting community