https://github.com/dsnchz/solid-plotly
SolidJS wrapper for Plotly.js – reactive and performant charts powered by Plotly, built for Solid.
https://github.com/dsnchz/solid-plotly
analysis analytics charting-library charts data-visualization solidjs visualization
Last synced: 4 months ago
JSON representation
SolidJS wrapper for Plotly.js – reactive and performant charts powered by Plotly, built for Solid.
- Host: GitHub
- URL: https://github.com/dsnchz/solid-plotly
- Owner: dsnchz
- License: mit
- Created: 2025-05-27T20:44:23.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-06-05T17:06:44.000Z (8 months ago)
- Last Synced: 2025-09-16T19:55:50.994Z (5 months ago)
- Topics: analysis, analytics, charting-library, charts, data-visualization, solidjs, visualization
- Language: TypeScript
- Homepage:
- Size: 147 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# @dschz/solid-plotly
[](LICENSE)
[](https://www.npmjs.com/package/@dschz/solid-plotly)
[](https://bundlephobia.com/package/@dschz/solid-plotly)
[](https://jsr.io/@dschz/solid-plotly)
[](https://github.com/dsnchz/solid-plotly/actions/workflows/ci.yaml)
[](https://discord.gg/XUVHnhsHKK)
> A modern, type-safe SolidJS component for [Plotly.js](https://plotly.com/javascript/) charts with fine-grained reactivity and full event support.
## ✨ Features
- 🏭 **Factory Pattern** - Plotly-agnostic design, bring your own Plotly.js bundle
- ⚡ **SolidJS Reactivity** - Fine-grained reactive updates for optimal performance
- 📱 **Responsive by Default** - Automatic resizing with ResizeObserver
- 🎯 **Full TypeScript Support** - Complete type safety with comprehensive JSDoc
- 🎪 **30+ Event Handlers** - All official Plotly.js events supported
## Contents
- [Installation](#installation)
- [Plotly.js Distribution](#plotlyjs-distribution)
- [Quick Start](#quick-start)
- [API Reference](#api-reference)
- [Factory Function](#factory-function)
- [Component Props](#component-props)
- [Event Handlers](#event-handlers)
- [Examples](#examples)
- [Customizing Plotly.js Bundle](#customizing-plotlyjs-bundle)
- [TypeScript Usage](#typescript-usage)
- [Development](#development)
## Installation
```bash
npm install solid-js @dschz/solid-plotly
# or
pnpm add solid-js @dschz/solid-plotly
# or
yarn add solid-js @dschz/solid-plotly
# or
bun add solid-js @dschz/solid-plotly
```
## Plotly.js Distribution
**Important**: You must also install a Plotly.js distribution that suits your needs. This library is designed to be Plotly-agnostic, allowing you to choose the which PLotly distribution is optimal for the needs of your application.
### For Web Applications (Recommended)
```bash
npm install plotly.js-dist-min
```
### Other Available Distributions
```bash
# Full bundle (~3MB) - All chart types and features
npm install plotly.js-dist
# Basic bundle (~1MB) - Common chart types (scatter, bar, line, pie, etc.)
npm install plotly.js-basic-dist
# Minimal bundle (~400KB) - Essential charts only
npm install plotly.js-dist-min
# Custom build - Advanced users who want to cherry-pick modules
npm install plotly.js
```
## Quick Start
Create a Plot component using the factory function with your chosen Plotly.js bundle:
```tsx
import { createSignal } from "solid-js";
import Plotly from "plotly.js-dist-min";
import { createPlotComponent } from "@dschz/solid-plotly";
// Create the Plot component bound to your Plotly module
const Plot = createPlotComponent(Plotly);
function App() {
return (
console.log("Clicked:", event.points)}
/>
);
}
```
## API Reference
### Factory Function
#### `createPlotComponent(Plotly: PlotlyModule)`
Creates a Plot component bound to a specific Plotly.js module.
**Parameters:**
- `Plotly` - Plotly.js module with required methods: `newPlot`, `react`, `purge`, `Plots`
**Returns:** SolidJS component for rendering Plotly charts
```tsx
import Plotly from "plotly.js-basic-dist";
import { createPlotComponent } from "@dschz/solid-plotly";
const Plot = createPlotComponent(Plotly);
```
### Component Props
| Prop | Type | Default | Description |
| --------------- | ------------------------------ | --------------------------------------------------- | ---------------------------------------------------------- |
| `data` | `PlotlyData[]` | `[]` | Array of data traces to plot _(required)_ |
| `layout` | `PlotlyLayout` | `{}` | Layout configuration for axes, title, margins, etc. |
| `config` | `PlotlyConfig` | `{}` | Plotly configuration options for behavior and appearance |
| `frames` | `PlotlyFrame[]` | `[]` | Animation frames for animated plots |
| `useResize` | `boolean` | `true` | Enable automatic plot resizing when container size changes |
| `id` | `string` | `"solid-plotly"` | Unique identifier for the plot container element |
| `class` | `string` | `undefined` | CSS class name(s) to apply to the plot container |
| `style` | `JSX.CSSProperties` | `{ position: "relative", display: "inline-block" }` | Inline CSS styles for the plot container |
| `onInitialized` | `(figure, element) => void` | `undefined` | Callback fired when the plot is first initialized |
| `onUpdate` | `(figure, element) => void` | `undefined` | Callback fired when the plot data/layout is updated |
| `onPurge` | `(figure, element) => void` | `undefined` | Callback fired when the plot is purged/destroyed |
| `onResize` | `() => void` | `undefined` | Callback fired when the plot is resized |
| `onError` | `(error) => void` | `undefined` | Callback fired when an error occurs during plot operations |
| `ref` | `(el: HTMLDivElement) => void` | `undefined` | Ref callback to access the underlying HTML div element |
### Event Handlers
The component supports all official Plotly.js events through props. All event handlers are optional:
#### Mouse & Interaction Events
- `onClick` - Fired when a data point is clicked
- `onDoubleClick` - Fired when plot is double-clicked
- `onHover` - Fired when hovering over a data point
- `onUnhover` - Fired when mouse leaves a data point
#### Selection Events
- `onSelected` - Fired when data points are selected
- `onSelecting` - Fired continuously while selecting data points
- `onDeselect` - Fired when selection is cleared
#### Layout Events
- `onRelayout` - Fired when the plot layout is changed (zoom, pan, resize)
- `onRelayouting` - Fired continuously while the layout is being changed
- `onRestyle` - Fired when plot styling properties are changed
#### Legend Events
- `onLegendClick` - Fired when a legend item is clicked
- `onLegendDoubleClick` - Fired when a legend item is double-clicked
#### UI Element Events
- `onClickAnnotation` - Fired when an annotation is clicked
- `onSliderChange` - Fired when a slider value is changed
- `onSliderStart` - Fired when slider interaction starts
- `onSliderEnd` - Fired when slider interaction ends
#### Plot Lifecycle Events
- `onAfterPlot` - Fired after plot rendering completes
- `onBeforePlot` - Fired before plot rendering begins
- `onRedraw` - Fired when plot is redrawn
- `onAutoSize` - Fired when plot auto-resizes
#### Animation Events
- `onAnimated` - Fired after animation completes
- `onAnimatingFrame` - Fired when an animation frame is being processed
- `onAnimationInterrupted` - Fired when animation is interrupted
- `onTransitioning` - Fired during plot transitions
- `onTransitionInterrupted` - Fired when transition is interrupted
#### Export Events
- `onAfterExport` - Fired after export operation completes
- `onBeforeExport` - Fired before export operation begins
#### Framework Events
- `onFramework` - Fired for framework-specific events
- `onSunburstClick` - Fired when a sunburst chart segment is clicked
- `onEvent` - Generic event handler for any plot event
## Examples
### Reactive Data Updates
```tsx
import { createSignal } from "solid-js";
import Plotly from "plotly.js-dist-min";
import { createPlotComponent, type PlotlyData } from "@dschz/solid-plotly";
const Plot = createPlotComponent(Plotly);
function ReactivePlot() {
const [data, setData] = createSignal([
{ x: [1, 2, 3], y: [1, 4, 2], type: "scatter" },
]);
const addPoint = () => {
setData((prev) => [
{
...prev[0],
x: [...prev[0].x, prev[0].x.length + 1],
y: [...prev[0].y, Math.random() * 10],
},
]);
};
return (
Add Point
);
}
```
### Event Handling
```tsx
import { createSignal } from "solid-js";
import type { PlotSelectionEvent } from "plotly.js";
import { createPlotComponent, type PlotlyData, type PlotlyLayout } from "@dschz/solid-plotly";
const Plot = createPlotComponent(Plotly);
function InteractivePlot() {
const [selectedPoints, setSelectedPoints] = createSignal([]);
const [data] = createSignal([
{ x: [1, 2, 3, 4], y: [10, 11, 12, 13], type: "scatter" },
]);
const [layout] = createSignal({ title: "Click and Select Points" });
return (
{
console.log("Clicked point:", event.points[0]);
}}
onSelected={(event) => {
setSelectedPoints(event.points);
console.log("Selected points:", event.points.length);
}}
onRelayout={(event) => {
console.log("Layout changed:", event);
}}
/>
);
}
```
### Responsive Layout
```tsx
import { createSignal } from "solid-js";
import { createPlotComponent, type PlotlyData, type PlotlyLayout } from "@dschz/solid-plotly";
const Plot = createPlotComponent(Plotly);
function ResponsivePlot() {
const [data] = createSignal([{ x: [1, 2, 3], y: [1, 4, 2], type: "scatter" }]);
const [layout] = createSignal({ title: "Responsive Chart" });
return (
);
}
```
### Animation
```tsx
import { createSignal, createEffect, onCleanup } from "solid-js";
import { createPlotComponent, type PlotlyData, type PlotlyLayout } from "@dschz/solid-plotly";
const Plot = createPlotComponent(Plotly);
function AnimatedPlot() {
const [frame, setFrame] = createSignal(0);
const [isAnimating, setIsAnimating] = createSignal(false);
const [layout] = createSignal({ title: "Animated Sine Wave" });
createEffect(() => {
if (!isAnimating()) return;
const interval = setInterval(() => {
setFrame((prev) => (prev + 1) % 60);
}, 100);
onCleanup(() => clearInterval(interval));
});
const data = (): PlotlyData[] => [
{
x: Array.from({ length: 50 }, (_, i) => i * 0.1),
y: Array.from({ length: 50 }, (_, i) => Math.sin(i * 0.1 + frame() * 0.1)),
type: "scatter",
mode: "lines",
},
];
return (
setIsAnimating(!isAnimating())}>
{isAnimating() ? "Stop" : "Start"} Animation
);
}
```
## Customizing Plotly.js Bundle
Choose the Plotly.js bundle that best fits your needs:
```tsx
// Full bundle (~3MB) - All chart types
import Plotly from "plotly.js-dist";
const Plot = createPlotComponent(Plotly);
// Basic bundle (~1MB) - Common chart types
import Plotly from "plotly.js-basic-dist";
const Plot = createPlotComponent(Plotly);
// Minimal bundle (~400KB) - Essential charts only
import Plotly from "plotly.js-dist-min";
const Plot = createPlotComponent(Plotly);
```
## TypeScript Usage
The library provides comprehensive TypeScript support with utility types to reduce friction when defining your chart data and configurations:
```tsx
import { createSignal } from "solid-js";
import {
createPlotComponent,
type PlotlyData,
type PlotlyLayout,
type PlotlyConfig,
type PlotlyFigure,
type PlotProps,
} from "@dschz/solid-plotly";
// Use utility types for your signals
const [data, setData] = createSignal([
{ x: [1, 2, 3], y: [1, 4, 2], type: "scatter" },
]);
const [layout, setLayout] = createSignal({
title: "My Chart",
xaxis: { title: "X Axis" },
yaxis: { title: "Y Axis" },
});
const [config, setConfig] = createSignal({
displayModeBar: true,
responsive: true,
});
// Type-safe callbacks
const handleInitialized = (figure: PlotlyFigure, element: PlotlyHTMLElement) => {
console.log("Initialized with", figure.data.length, "traces");
setData(figure.data);
setLayout(figure.layout);
};
// Create your Plot component
const Plot = createPlotComponent(Plotly);
function MyChart() {
return (
);
}
```
### Available Utility Types
- **`PlotlyData`** - Single data trace type (use `PlotlyData[]` for the data prop)
- **`PlotlyLayout`** - Layout configuration object
- **`PlotlyConfig`** - Plotly configuration options
- **`PlotlyFrame`** - Animation frame type (use `PlotlyFrame[]` for frames prop)
- **`PlotlyFigure`** - Complete figure data structure (used in callbacks)
- **`PlotProps`** - Complete props interface for the Plot component
- **`PlotlyModule`** - Type for the Plotly.js module interface
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
For more examples and detailed documentation, visit the [GitHub repository](https://github.com/dsnchz/solid-plotly) or check out the [Discord](https://discord.gg/XUVHnhsHKK) community.
## License
MIT License