A powerful streaming data visualization library based on the Grammar of Graphics. Designed for real-time data visualization with support for time series, bar/column charts, single value metrics, and data tables.
Introduction Blog https://www.timeplus.com/post/vistral
Examples and Playground can be found here https://timeplus-io.github.io/vistral/
Introduction Presentation https://timeplus-io.github.io/gg-vistral-introduction/
Concept Introduction https://timeplus-io.github.io/vistra-temporal-binding/
API Reference docs/api-reference.md
Design Principles docs/design-principles.md
Table of Contents
- Features
- Installation
- Quick Start
- Chart Types
- Temporal Binding Modes
- Using Individual Chart Components
- Data Format
- Streaming Data with Hooks
- Color Palettes
- API Reference
- Design Principles
- Development
- Browser Support
- License
Features
- 📊 Multiple Chart Types: Line, Area, Bar, Column, Single Value, Data Table, and Geo Map
- 🔄 Streaming Support: Built for real-time data with efficient updates
- ⏱️ Temporal Binding: Three modes for handling streaming data (axis-bound, frame-bound, key-bound)
- 🎨 Beautiful Themes: Dark and light themes with customizable color palettes
- 📱 Responsive: Auto-fit to container with resize detection
- 🎯 TypeScript: Full TypeScript support with comprehensive types
- ⚡ Performant: Optimized for streaming data with minimal re-renders
- 🧩 Modular: Use the unified
StreamChartor individual chart components
Installation
NPM/Yarn/PNPM
npm install @timeplus/vistral
UMD (Browser/CDN)
Vistral is available as a UMD bundle, allowing you to use it directly in the browser via script tags.
<!-- 1. Dependencies --> <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/lodash@4/lodash.min.js"></script> <script src="https://unpkg.com/ramda@0.29/dist/ramda.min.js"></script> <script src="https://unpkg.com/@antv/g2@5/dist/g2.min.js"></script> <script src="https://unpkg.com/@antv/s2@2/dist/s2.min.js"></script> <!-- 2. Vistral --> <script src="https://unpkg.com/@timeplus/vistral/dist/index.umd.min.js"></script> <!-- 3. Usage --> <script> const { Vistral, React, ReactDOM } = window; const { StreamChart } = Vistral; const data = { columns: [{ name: 'val', type: 'number' }], data: [{ val: 10 }, { val: 20 }] }; const config = { chartType: 'table' }; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(React.createElement(StreamChart, { data, config })); </script>
Peer Dependencies
Make sure you have React installed (if using NPM):
npm install react react-dom
Quick Start
import { StreamChart } from '@timeplus/vistral'; function App() { const data = { columns: [ { name: 'timestamp', type: 'datetime64' }, { name: 'value', type: 'float64' }, { name: 'category', type: 'string' }, ], data: [ ['2024-01-01T10:00:00Z', 42.5, 'A'], ['2024-01-01T10:01:00Z', 45.2, 'A'], ['2024-01-01T10:02:00Z', 38.1, 'B'], // ... more data ], }; const config = { chartType: 'line', xAxis: 'timestamp', yAxis: 'value', color: 'category', legend: true, gridlines: true, }; return ( <div style={{ width: '100%', height: '400px' }}> <StreamChart config={config} data={data} theme="dark" /> </div> ); }
Chart Types
Line Chart
Perfect for time series data showing trends over time.
import { StreamChart } from '@timeplus/vistral'; <StreamChart config={{ chartType: 'line', xAxis: 'timestamp', yAxis: 'value', color: 'series', lineStyle: 'curve', // or 'straight' points: true, legend: true, gridlines: true, temporal: { mode: 'axis', field: 'timestamp', range: 5, // Show last 5 minutes }, fractionDigits: 2, }} data={data} theme="dark" />
Area Chart
Similar to line charts but with filled areas, great for showing volume or stacked data.
<StreamChart config={{ chartType: 'area', xAxis: 'timestamp', yAxis: 'value', color: 'category', // Creates stacked areas legend: true, }} data={data} />
Bar Chart (Horizontal)
Horizontal bar charts for categorical comparisons.
<StreamChart config={{ chartType: 'bar', xAxis: 'category', yAxis: 'value', color: 'subcategory', groupType: 'stack', // or 'dodge' dataLabel: true, }} data={data} />
Column Chart (Vertical)
Vertical column charts for categorical data.
<StreamChart config={{ chartType: 'column', xAxis: 'month', yAxis: 'sales', color: 'region', groupType: 'dodge', gridlines: true, }} data={data} />
Single Value
Display a single metric with optional sparkline and delta indicator.
<StreamChart config={{ chartType: 'singleValue', yAxis: 'activeUsers', fontSize: 72, color: 'green', fractionDigits: 0, sparkline: true, delta: true, unit: { position: 'left', value: '$' }, }} data={data} />
Multiple Value
Display multiple values side-by-side, split by a specific key. Key bound is required.
<StreamChart config={{ chartType: 'multipleValue', yAxis: 'cpu_usage', key: 'server_id', fontSize: 48, color: 'cyan', fractionDigits: 0, sparkline: true, delta: true, unit: { position: 'right', value: '%' }, }} data={data} />
Data Table
Display streaming data in a tabular format with column configuration.
<StreamChart config={{ chartType: 'table', tableStyles: { timestamp: { name: 'Time', width: 200 }, value: { name: 'Value', miniChart: 'sparkline', color: { type: 'condition', conditions: [ { operator: 'gt', value: 100, color: '#22C55E' }, { operator: 'lt', value: 50, color: '#EF4444' }, ], }, }, }, temporal: { mode: 'key', // Deduplicate by key field: 'id', }, }} data={data} />
Geo Chart
Display geographic data points on an interactive map with pan and zoom.
<StreamChart config={{ chartType: 'geo', latitude: 'lat', longitude: 'lng', color: 'category', // Color points by category size: { key: 'value', // Size points by value min: 4, max: 20, }, zoom: 3, center: [40.7128, -74.006], // [lat, lng] showZoomControl: true, showCenterDisplay: true, pointOpacity: 0.8, }} data={data} />
Temporal Binding Modes
Vistral provides three temporal binding modes for handling streaming data:
| Mode | Description | Use Case |
|---|---|---|
| axis | Time mapped to axis with sliding window | Time-series trends |
| frame | Only latest timestamp visible | Real-time snapshots |
| key | Latest value per unique key | Live dashboards |
Axis-Bound (Sliding Window)
For time series charts, shows a sliding time window:
<StreamChart config={{ chartType: 'line', xAxis: 'timestamp', yAxis: 'value', temporal: { mode: 'axis', field: 'timestamp', range: 5, // 5-minute window }, }} data={data} />
Frame-Bound (Latest Timestamp)
Shows only rows with the latest timestamp - useful for real-time snapshots:
<StreamChart config={{ chartType: 'table', temporal: { mode: 'frame', field: 'timestamp', }, }} data={data} />
Key-Bound (Deduplicate by Key)
Keeps the latest value for each unique key. Supports composite keys by passing an array of fields:
<StreamChart config={{ chartType: 'geo', latitude: 'lat', longitude: 'lng', temporal: { mode: 'key', field: ['region', 'vehicle_id'], // Composite key }, }} data={data} />
Using Individual Chart Components
For complex use cases not covered by StreamChart, you can use the lower-level VistralChart with a raw grammar specification, or the specialized SingleValueChart and DataTable components.
import { VistralChart, SingleValueChart, DataTable } from '@timeplus/vistral'; // Advanced: Use Grammar directly <VistralChart spec={mySpec} source={data} /> // Specialized Components <SingleValueChart config={config} data={data} theme="dark" /> <DataTable config={config} data={data} theme="dark" />
Data Format
StreamDataSource
interface StreamDataSource { columns: ColumnDefinition[]; data: DataRow[]; isStreaming?: boolean; } interface ColumnDefinition { name: string; type: string; // 'string' | 'number' | 'datetime64' | 'float64' | etc. nullable?: boolean; } // Data rows can be arrays or objects type DataRow = unknown[] | Record<string, unknown>;
Example with Array Format
const data = { columns: [ { name: 'time', type: 'datetime64' }, { name: 'cpu', type: 'float64' }, { name: 'memory', type: 'float64' }, ], data: [ [1704067200000, 45.2, 62.1], [1704067260000, 48.1, 63.5], [1704067320000, 42.8, 61.2], ], };
Example with Object Format
const data = { columns: [ { name: 'time', type: 'datetime64' }, { name: 'cpu', type: 'float64' }, ], data: [ { time: '2024-01-01T10:00:00Z', cpu: 45.2 }, { time: '2024-01-01T10:01:00Z', cpu: 48.1 }, ], };
Streaming Data with Hooks
Use the provided hooks for managing streaming data:
import { StreamChart, useStreamingData } from '@timeplus/vistral'; function LiveChart() { const { data, append, clear } = useStreamingData([], 1000); // Max 1000 items useEffect(() => { const ws = new WebSocket('ws://your-streaming-endpoint'); ws.onmessage = (event) => { const newData = JSON.parse(event.data); append(newData); }; return () => ws.close(); }, [append]); return ( <StreamChart config={config} data={{ columns: [...], data: data, isStreaming: true, }} /> ); }
Color Palettes
Built-in Palettes
import { multiColorPalettes, singleColorPalettes, findPaletteByLabel } from '@timeplus/vistral'; // Multi-color palettes for categorical data // Available: 'Dawn', 'Morning', 'Midnight', 'Ocean', 'Sunset' // Single-color palettes for sequential data // Available: 'red', 'pink', 'purple', 'blue', 'green', 'orange', 'yellow', 'cyan', 'gray' // Use by label const palette = findPaletteByLabel('Dawn'); // Apply to chart <StreamChart config={{ chartType: 'line', xAxis: 'time', yAxis: 'value', colors: palette.values, }} data={data} />
Custom Colors
<StreamChart config={{ chartType: 'line', xAxis: 'time', yAxis: 'value', colors: ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'], }} data={data} />
API Reference
For detailed API documentation including configuration options for all chart types, hooks, and utilities, see the API Reference.
Development
Prerequisites
- Node.js >= 16
- npm, yarn, or pnpm
Setup
# Clone the repository git clone https://github.com/timeplus-io/vistral.git cd vistral # Install dependencies npm install
Scripts
| Command | Description |
|---|---|
npm run build |
Build the library (CommonJS + ESM + TypeScript declarations) |
npm run dev |
Start development mode with watch (library rebuild) |
npm run dev:examples |
Start Vite dev server to view examples at http://localhost:3000 |
npm run test |
Run tests with Vitest |
npm run test:coverage |
Run tests with coverage report |
npm run lint |
Run ESLint |
npm run typecheck |
Run TypeScript type checking |
Viewing Examples
To view the interactive examples during development:
# Install dependencies first npm install # Start the examples dev server npm run dev:examples
This will open http://localhost:3000 with a sidebar navigation showing all available chart examples.
Credits
Built with:
- AntV G2 - Visualization grammar
- React - UI framework
- TypeScript - Type safety
Developed by Timeplus








