https://github.com/dsnchz/solid-uplot

SolidJS wrapper for uPlot — an ultra-fast, tiny time-series & charting library with a SolidJS enhanced plugin system

https://github.com/dsnchz/solid-uplot

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (10.1%) to scientific vocabulary

Keywords

analysis canvas canvas-chart canvas-chart-library charting-library charts data-analysis data-analytics data-visualization solidjs trading visualization
Last synced: 5 months ago · JSON representation

Repository

SolidJS wrapper for uPlot — an ultra-fast, tiny time-series & charting library with a SolidJS enhanced plugin system

Basic Info
  • Host: GitHub
  • Owner: dsnchz
  • License: mit
  • Language: TypeScript
  • Default Branch: main
  • Homepage:
  • Size: 267 KB
Statistics
  • Stars: 13
  • Watchers: 1
  • Forks: 0
  • Open Issues: 0
  • Releases: 0
Topics
analysis canvas canvas-chart canvas-chart-library charting-library charts data-analysis data-analytics data-visualization solidjs trading visualization
Created 9 months ago · Last pushed 8 months ago
Metadata Files
Readme Changelog License Codeowners

README.md

@dschz/solid-uplot banner

@dschz/solid-uplot

License uPlot npm Bundle Size JSR CI Discord

💹 SolidJS wrapper for uPlot — an ultra-fast, small footprint charting library for time-series data.

✨ Features

  • ✅ Fully reactive SolidJS wrapper around uPlot
  • 🔌 Plugin system support with inter-plugin communication
  • 🎯 Fine-grained control over chart lifecycle
  • 💡 Lightweight and fast
  • 💻 TypeScript support out of the box
  • 🎨 Built-in plugins for tooltips, legends, cursor tracking, and series focusing
  • 📱 Responsive sizing support with auto-resize capabilities

📦 Installation

bash npm install solid-js uplot @dschz/solid-uplot pnpm install solid-js uplot @dschz/solid-uplot yarn install solid-js uplot @dschz/solid-uplot bun install solid-js uplot @dschz/solid-uplot

📁 Package Structure

This package provides three main export paths for different functionality:

@dschz/solid-uplot

Core components and plugin system:

tsx import { SolidUplot, createPluginBus } from "@dschz/solid-uplot"; import type { SolidUplotPluginBus, UplotPluginFactory, UplotPluginFactoryContext, } from "@dschz/solid-uplot";

@dschz/solid-uplot/plugins

This export path provides four plugins (three of which can be considered primitives).

  • cursor: transmits cursor position data
  • focusSeries: transmits which series are visually emphasized
  • tooltip: plugin that allows you to present a custom JSX tooltip around the cursor
  • legend: plugin that allows you to present a custom JSX component as your legend over the canvas drawing area.

tsx import { cursor, tooltip, legend, focusSeries } from "@dschz/solid-uplot/plugins"; import type { CursorPluginMessageBus, FocusSeriesPluginMessageBus, TooltipProps, LegendProps, } from "@dschz/solid-uplot/plugins";

@dschz/solid-uplot/utils

Some convenience utility functions for getting certain bits of data from a uPlot instance (except for getColorString which translates a series' stroke or fill into a color value).

tsx import { getSeriesData, getCursorData, getColorString, getNewCalendarDayIndices, } from "@dschz/solid-uplot/utils"; import type { SeriesDatum, CursorData } from "@dschz/solid-uplot/utils";

🚀 Quick Start

```tsx import { SolidUplot, createPluginBus } from "@dschz/solid-uplot"; import { cursor, tooltip, legend } from "@dschz/solid-uplot/plugins"; import type { CursorPluginMessageBus, TooltipProps, LegendProps } from "@dschz/solid-uplot/plugins";

// Create a tooltip component const MyTooltip = (props: TooltipProps) => (

X: {props.cursor.xValue}
{(series) => { const value = props.u.data[series.seriesIdx]?.[props.cursor.idx]; return (
{series.label}: {value}
); }}
);

// Create a legend component const MyLegend = (props: LegendProps) => (

{(series) => (
{series.label}
)}
);

const MyChart = () => { const bus = createPluginBus();

return ( ); }; ```

📏 Responsive Sizing

For responsive charts that automatically adapt to container size changes, use the autoResize prop:

tsx <div style={{ width: "100%", height: "400px" }}> <SolidUplot autoResize={true} data={data} series={series} // Chart will automatically resize to fill the container /> </div>

For more advanced responsive patterns, you can pair this library with @dschz/solid-auto-sizer:

bash npm install @dschz/solid-auto-sizer pnpm install @dschz/solid-auto-sizer yarn install @dschz/solid-auto-sizer bun install @dschz/solid-auto-sizer

```tsx import { AutoSizer } from "@dschz/solid-auto-sizer";

{({ width, height }) => } ; ```

🔌 Enhanced Plugin System

The cornerstone feature of SolidUplot is its refined plugin system that enables extensible functionality and inter-plugin communication through a reactive message bus.

Plugin Bus Architecture

The Plugin Bus System enables plugins to communicate with each other and external components through a reactive store. This architecture provides:

  • Type-safe communication: All plugin messages are fully typed
  • Reactive updates: Changes in plugin state automatically trigger updates
  • Decoupled components: Plugins can interact without direct dependencies
  • Extensible: Easy to add new plugins that integrate with existing ones

Built-in Plugins

Cursor Plugin

Tracks cursor position and interaction state across charts:

```tsx import { cursor } from "@dschz/solid-uplot/plugins"; import type { CursorPluginMessageBus } from "@dschz/solid-uplot/plugins";

const cursorPlugin = cursor(); ```

The cursor plugin provides cursor position data that other plugins can consume through the bus.

Focus Series Plugin

Highlights series based on cursor proximity:

```tsx import { focusSeries } from "@dschz/solid-uplot/plugins"; import type { FocusSeriesPluginMessageBus } from "@dschz/solid-uplot/plugins";

const focusPlugin = focusSeries({ pxThreshold: 15, // Distance threshold for focusing (default: 15) }); ```

Tooltip Plugin

Renders custom tooltips with automatic positioning and overflow handling:

```tsx import { tooltip } from "@dschz/solid-uplot/plugins"; import type { TooltipProps } from "@dschz/solid-uplot/plugins";

const MyTooltip: Component = (props) => { return (

X: {props.cursor.xValue}
{(series) => { const value = () => props.u.data[series.seriesIdx]?.[props.cursor.idx]; return (
{series.label}: {value()?.toFixed(2)}
); }}
); };

const tooltipPlugin = tooltip(MyTooltip, { placement: "top-left", // "top-left" | "top-right" | "bottom-left" | "bottom-right" zIndex: 20, }); ```

Legend Plugin

Adds customizable legends with smart positioning and interactive features:

```tsx import { legend } from "@dschz/solid-uplot/plugins"; import type { LegendProps } from "@dschz/solid-uplot/plugins";

const MyLegend: Component = (props) => { // Access cursor data for interactive features const cursorVisible = () => props.bus.data.cursor?.state[props.u.root.id]?.visible;

return (

Legend
{(series) => (
{series.label}
)}
); };

const legendPlugin = legend(MyLegend, { placement: "top-left", // "top-left" | "top-right" pxOffset: 8, // Distance from chart edges (default: 8) zIndex: 10, }); ```

Legend Plugin Features:

  • Simple positioning: Only top-left or top-right corners to avoid axis conflicts
  • Size-constrained: Legend cannot exceed chart drawing area dimensions
  • Layout-agnostic: You control internal layout and styling
  • Non-interfering: Designed to work harmoniously with chart interactions
  • Plugin bus integration: Access cursor and focus data for smart interactions
  • Automatic cleanup: Proper memory management and DOM cleanup

Plugin Bus Type Safety

When using multiple plugins, ensure type safety by properly typing the plugin bus:

```tsx import { createPluginBus } from "@dschz/solid-uplot"; import type { CursorPluginMessageBus, FocusSeriesPluginMessageBus, } from "@dschz/solid-uplot/plugins";

// Create a bus that includes all plugin message types const bus = createPluginBus();

const MyChart = () => { return ( ); }; ```

Creating Custom Plugins

The plugin system is open to extension. When authoring plugins for public consumption, follow this pattern:

```tsx import type { UplotPluginFactory } from "@dschz/solid-uplot"; import type { CursorPluginMessageBus } from "@dschz/solid-uplot/plugins";

// 1. Define your plugin's message type export type MyPluginMessage = { value: number; timestamp: number; };

// 2. Define your plugin's message bus export type MyPluginMessageBus = { myPlugin?: MyPluginMessage; };

// 3. Export your plugin factory export const myPlugin = ( options = {}, ): UplotPluginFactory => { return ({ bus }) => { if (!bus) { console.warn("[my-plugin]: A plugin bus is required"); return { hooks: {} }; }

return {
  hooks: {
    ready: (u) => {
      // Initialize plugin state
      bus.setData("myPlugin", {
        value: 0,
        timestamp: Date.now(),
      });
    },
    setData: (u) => {
      // Update plugin state
      bus.setData("myPlugin", "value", (prev) => prev + 1);
    },
  },
};

}; }; ```

External Component Integration

The plugin bus enables powerful integrations between charts and external components:

```tsx import { createPluginBus } from "@dschz/solid-uplot"; import type { FocusSeriesPluginMessageBus } from "@dschz/solid-uplot/plugins";

const bus = createPluginBus();

// External component that can trigger series focus const DataGrid = (props: { bus: typeof bus }) => { const handleRowHover = (seriesLabel: string) => { props.bus.setData("focusSeries", { sourceId: "data-grid", targets: [{ label: seriesLabel }], }); };

return

{/* Grid implementation */}
; };

// Chart and grid interact through shared bus const MyDashboard = () => { return (

); }; ```

🔧 API Reference

SolidUplot Component

```tsx type SolidUplotEvents = { /** Callback fired when the uPlot instance is created / readonly onCreate?: (u: uPlot, meta: OnCreateMeta) => void; /* Callback fired when the cursor moves */ readonly onCursorMove?: (params: OnCursorMoveParams) => void; };

// Main component props (extends all uPlot.Options except plugins, width, height) type SolidUplotProps = SolidUplotOptions & SolidUplotEvents & { // Ref callback to access the chart container element ref?: Ref;

// CSS class name for the chart container (default: "solid-uplot")
// Additional classes will be appended to the default class
class?: string;

// CSS styles for the chart container (position is managed internally)
style?: Omit<JSX.CSSProperties, "position">;

// Enable automatic resizing to fit container (default: false)
autoResize?: boolean;

// Whether to reset scales when chart data is updated (default: true)
resetScales?: boolean;

// Where to place children components relative to the chart (default: "top")
childrenPlacement?: "top" | "bottom";

};

// Configuration options extending uPlot.Options with SolidJS enhancements type SolidUplotOptions = Omit< uPlot.Options, "plugins" | "width" | "height"

& { // Chart dimensions width?: number; // default: 600 height?: number; // default: 300

// Plugin configuration plugins?: SolidUplotPlugin[]; pluginBus?: SolidUplotPluginBus; };

// Plugin type (can be standard uPlot plugin or factory function) type SolidUplotPlugin = uPlot.Plugin | UplotPluginFactory; ```

Plugin Bus

```tsx // Plugin bus type (derived from createPluginBus return type) type SolidUplotPluginBus = ReturnType>;

// Create a plugin bus const createPluginBus: ( initialData?: T, ) => SolidUplotPluginBus; ```

Built-in Plugin Options

```tsx // Cursor Plugin const cursor = (): UplotPluginFactory;

// Focus Series Plugin const focusSeries = (options?: { pxThreshold?: number; // default: 15 }): UplotPluginFactory;

// Tooltip Plugin const tooltip = ( Component: Component, options?: { placement?: "top-left" | "top-right" | "bottom-left" | "bottom-right"; id?: string; class?: string; style?: JSX.CSSProperties; zIndex?: number; // default: 20 } ): UplotPluginFactory;

// Legend Plugin const legend = ( Component: Component, options?: { placement?: "top-left" | "top-right"; // default: "top-left" pxOffset?: number; // default: 8 id?: string; class?: string; style?: JSX.CSSProperties; zIndex?: number; // default: 10 } ): UplotPluginFactory; ```

📚 Examples

Basic Chart

```tsx import { SolidUplot } from "@dschz/solid-uplot";

const BasicChart = () => { return ( ); }; ```

Chart with All Plugins

```tsx import { SolidUplot, createPluginBus } from "@dschz/solid-uplot"; import { cursor, tooltip, legend, focusSeries } from "@dschz/solid-uplot/plugins"; import type { CursorPluginMessageBus, FocusSeriesPluginMessageBus, TooltipProps, LegendProps, } from "@dschz/solid-uplot/plugins";

const MyTooltip: Component = (props) => (

Time: {new Date(props.cursor.xValue * 1000).toLocaleTimeString()}
{(series) => { const value = props.u.data[series.seriesIdx]?.[props.cursor.idx]; return (
{series.label}: {value?.toFixed(2)}
); }}
);

const MyLegend: Component = (props) => { const cursorVisible = () => props.bus.data.cursor?.state[props.u.root.id]?.visible;

return (

{(series) => (
{series.label}
)}
); };

const FullFeaturedChart = () => { const bus = createPluginBus();

return ( ); }; ```

Responsive Chart

tsx const ResponsiveChart = () => { return ( <div style={{ width: "100%", height: "400px", border: "1px solid #ccc" }}> <SolidUplot autoResize={true} data={data} series={series} plugins={[cursor(), tooltip(MyTooltip)]} /> </div> ); };

External Integration

```tsx const Dashboard = () => { const bus = createPluginBus();

const handleSeriesToggle = (seriesLabel: string) => { bus.setData("focusSeries", { sourceId: "external-control", targets: [{ label: seriesLabel }], }); };

return (

); }; ```

🎮 Interactive Playground

This library includes a comprehensive playground application that demonstrates all features and provides interactive examples. The playground showcases:

  • Basic Charts: Simple line charts with different configurations
  • Plugin Examples: All built-in plugins working together
  • Legend Showcase: Various legend patterns and interactions
  • Responsive Sizing: Auto-resize and manual sizing examples
  • Custom Plugins: Examples of creating your own plugins
  • External Integration: Charts interacting with external components

Running the Playground Locally

To explore the playground and see the library in action:

```bash

Clone the repository

git clone https://github.com/dsnchz/solid-uplot.git cd solid-uplot

Install dependencies

npm install

or

pnpm install

or

yarn install

or

bun install

Start the playground development server

npm run start

or

pnpm start

or

yarn start

or

bun start ```

The playground will be available at http://localhost:3000 and includes:

  • Live code examples with syntax highlighting
  • Interactive demos you can modify in real-time
  • Performance comparisons between different configurations
  • Best practices and common patterns
  • Plugin development examples with step-by-step guides

The playground source code also serves as a comprehensive reference for implementing various chart patterns and plugin combinations.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Also check out the Discord community.

📄 License

MIT

Owner

  • Name: dsnchz
  • Login: dsnchz
  • Kind: organization

GitHub Events

Total
  • Release event: 2
  • Watch event: 6
  • Public event: 1
  • Push event: 6
  • Create event: 5
Last Year
  • Release event: 2
  • Watch event: 6
  • Public event: 1
  • Push event: 6
  • Create event: 5

Packages

  • Total packages: 2
  • Total downloads:
    • npm 213 last-month
  • Total dependent packages: 0
    (may contain duplicates)
  • Total dependent repositories: 0
    (may contain duplicates)
  • Total versions: 10
  • Total maintainers: 1
npmjs.org: @dschz/solid-flow

Solid Flow - A highly customizable Solid library for building node-based editors, workflow systems, diagrams and more.

  • Versions: 1
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent repos count: 23.9%
Average: 29.2%
Dependent packages count: 34.5%
Maintainers (1)
Last synced: 6 months ago
npmjs.org: @dschz/solid-uplot

SolidJS wrapper for uPlot — ultra-fast, tiny time-series & charting library

  • Versions: 9
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 213 Last month
Rankings
Dependent repos count: 24.6%
Average: 30.0%
Dependent packages count: 35.4%
Maintainers (1)
Last synced: 6 months ago

Dependencies

.github/workflows/ci.yaml actions
  • actions/checkout v4 composite
  • oven-sh/setup-bun v1 composite
package.json npm
  • @changesets/cli ^2.29.3 development
  • @dschz/solid-auto-sizer ^0.1.0 development
  • @solidjs/router ^0.15.3 development
  • @solidjs/testing-library ^0.8.10 development
  • @tailwindcss/vite ^4.1.5 development
  • @testing-library/jest-dom ^6.6.3 development
  • @testing-library/user-event ^14.6.1 development
  • @types/bun ^1.2.12 development
  • @types/prismjs ^1.26.3 development
  • @typescript-eslint/eslint-plugin ^8.32.0 development
  • @typescript-eslint/parser ^8.32.0 development
  • @vitest/coverage-istanbul ^3.1.3 development
  • @wessberg/pointer-events ^1.0.9 development
  • canvas ^3.1.0 development
  • eslint ^9.26.0 development
  • eslint-plugin-simple-import-sort ^12.1.1 development
  • eslint-plugin-solid ^0.14.5 development
  • globals ^16.1.0 development
  • jiti ^2.4.2 development
  • jsdom ^26.1.0 development
  • path2d ^0.2.2 development
  • prettier ^3.5.3 development
  • prismjs ^1.29.0 development
  • solid-js ^1.9.6 development
  • solid-prism-editor ^2.0.0 development
  • tailwindcss ^4.1.5 development
  • tsup ^8.4.0 development
  • tsup-preset-solid ^2.2.0 development
  • typescript ^5.8.3 development
  • typescript-eslint ^8.32.0 development
  • uplot ^1.6.32 development
  • vite ^6.3.5 development
  • vite-plugin-solid ^2.11.6 development
  • vitest ^3.1.3 development