Skip to content

Commit ff2ea6d

Browse files
authored
Merge pull request #10 from ChartGPU/upgrade-chartgpu-version
Upgrade ChartGPU React bindings to the latest core package and expand the public API surface for advanced sync and interaction workflows.
2 parents e790583 + bffed10 commit ff2ea6d

21 files changed

+389
-151
lines changed

README.md

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
1-
# chartgpu-react
1+
<p align="center" style="margin-bottom:0; margin-top:20px;">
2+
<img src="docs/assets/chartgpu.png" alt="ChartGPU" width="400">
3+
</p>
24

35
<p align="center">
4-
React bindings for <a href="https://github.com/ChartGPU/ChartGPU">ChartGPU</a> — WebGPU-powered charting for high-performance data visualization.
6+
React bindings for <a href="https://github.com/ChartGPU/ChartGPU">ChartGPU</a> — The fastest open-source charting library — 50M points at 60 FPS.
57
</p>
68

79
<div align="center">
810

11+
[<img src="docs/assets/powered-by-webgpu.svg" alt="Powered by WebGPU" height="28" />](https://forthebadge.com)
912
[![Documentation](https://img.shields.io/badge/Documentation-Getting%20Started-blue?style=for-the-badge)](https://github.com/chartgpu/chartgpu-react/blob/main/docs/GETTING_STARTED.md)
1013
[![API Reference](https://img.shields.io/badge/API-Reference-blue?style=for-the-badge)](https://github.com/chartgpu/chartgpu-react/blob/main/docs/API.md)
1114
[![Examples](https://img.shields.io/badge/Examples-Run%20Locally-blue?style=for-the-badge)](https://github.com/chartgpu/chartgpu-react/tree/main/examples)
12-
1315
[![npm version](https://img.shields.io/npm/v/chartgpu-react?style=for-the-badge&color=blue)](https://www.npmjs.com/package/chartgpu-react)
1416
[![NPM Downloads](https://img.shields.io/npm/dm/chartgpu-react?style=for-the-badge&color=%2368cc49)](https://www.npmjs.com/package/chartgpu-react)
1517
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://www.npmjs.com/package/chartgpu-react)
1618

19+
[<img src="https://hackerbadge.now.sh/api?id=46706528" alt="Featured on Hacker News" height="30" />](https://news.ycombinator.com/item?id=46706528)
20+
21+
[<img src="https://awesome.re/mentioned-badge.svg" alt="Featured in Awesome WebGPU" style="height: 30px;" />](https://github.com/mikbry/awesome-webgpu)
22+
23+
1724
</div>
1825

19-
`chartgpu-react` is a **thin React + TypeScript wrapper** around the [`chartgpu`](https://www.npmjs.com/package/chartgpu) core library.
26+
`chartgpu-react` is a **thin React + TypeScript wrapper** around the [`@chartgpu/chartgpu`](https://www.npmjs.com/package/@chartgpu/chartgpu) core library.
2027

2128
## Highlights
2229

2330
- **`ChartGPU` component (recommended)**: async create/dispose lifecycle + debounced `ResizeObserver` sizing
2431
- **Event props**: `onClick`, `onCrosshairMove`, `onZoomChange`, etc.
25-
- **Imperative `ref` API**: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`)
26-
- **Hooks**: `useChartGPU(...)`, `useConnectCharts(...)`
27-
- **Helper re-exports (from `chartgpu`)**: `createChart`, `connectCharts`, `createAnnotationAuthoring`
32+
- **Imperative `ref` API**: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`)
33+
- **Hooks**: `useChartGPU(...)`, `useConnectCharts(..., syncOptions?)`
34+
- **Helper re-exports (from `@chartgpu/chartgpu`)**: `createChart`, `connectCharts`, `createAnnotationAuthoring`
2835

2936
## Quick start
3037

@@ -60,7 +67,7 @@ function MyChart() {
6067
## Installation
6168

6269
```bash
63-
npm install chartgpu-react chartgpu react react-dom
70+
npm install chartgpu-react @chartgpu/chartgpu react react-dom
6471
```
6572

6673
### Requirements
@@ -79,20 +86,20 @@ Check browser compatibility at [caniuse.com/webgpu](https://caniuse.com/webgpu).
7986
- lifecycle management (async create + dispose)
8087
- `ResizeObserver` resize (debounced)
8188
- event props: `onClick`, `onCrosshairMove`, `onZoomChange`, etc.
82-
- imperative `ref` API: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`)
89+
- imperative `ref` API: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`)
8390
- **Hooks**
8491
- `useChartGPU(containerRef, options)` — create/manage a chart instance
85-
- `useConnectCharts([chartA, chartB, ...])` — sync crosshair/interaction-x across charts
92+
- `useConnectCharts([chartA, chartB, ...], syncOptions?)` — sync crosshair/interaction-x (and optionally zoom) across charts
8693
- **Deprecated**
8794
- `ChartGPUChart` (legacy adapter; use `ChartGPU` instead)
88-
- **Helper re-exports** (from peer dependency `chartgpu`)
95+
- **Helper re-exports** (from peer dependency `@chartgpu/chartgpu`)
8996
- `createChart`, `connectCharts`, `createAnnotationAuthoring`
9097

9198
For details, start with the [API reference](./docs/API.md).
9299

93100
## Feature snippets (ChartGPU core)
94101

95-
These snippets use helpers and events from the `chartgpu` core library (peer dependency of `chartgpu-react`).
102+
These snippets use helpers and events from the `@chartgpu/chartgpu` core library (peer dependency of `chartgpu-react`).
96103

97104
### Crosshair / interaction X (`'crosshairMove'`)
98105

@@ -112,16 +119,19 @@ import type { ChartGPUCrosshairMovePayload } from 'chartgpu-react';
112119
### Connect charts (sync crosshair/tooltip)
113120

114121
```tsx
115-
import { connectCharts } from 'chartgpu';
122+
import { connectCharts } from 'chartgpu-react';
116123

117124
// When you have two ChartGPUInstance objects:
118125
const disconnect = connectCharts([chartA, chartB]);
119126

127+
// With zoom sync:
128+
// const disconnect = connectCharts([chartA, chartB], { syncZoom: true });
129+
120130
// Later:
121131
disconnect();
122132
```
123133

124-
If you prefer a hook-driven approach, you can use `onReady` (or `useChartGPU`) to capture instances, then call `connectCharts(...)` once both are available.
134+
If you prefer a hook-driven approach, you can use `onReady` (or `useChartGPU`) to capture instances, then call `useConnectCharts(...)` once both are available.
125135

126136
### Annotation authoring UI (`createAnnotationAuthoring`)
127137

@@ -158,7 +168,7 @@ function AnnotationAuthoringExample() {
158168
import { useEffect, useRef } from 'react';
159169
import { ChartGPU } from 'chartgpu-react';
160170
import type { ChartGPUHandle, ChartGPUOptions } from 'chartgpu-react';
161-
import type { OHLCDataPoint } from 'chartgpu';
171+
import type { OHLCDataPoint } from 'chartgpu-react';
162172

163173
function CandlestickStreaming() {
164174
const ref = useRef<ChartGPUHandle>(null);
@@ -232,28 +242,28 @@ The dev server will start at `http://localhost:3000` and open the examples page
232242

233243
### Local development with linked ChartGPU
234244

235-
To develop `chartgpu-react` against a local version of the `chartgpu` package (useful for testing changes across both repositories):
245+
To develop `chartgpu-react` against a local version of the `@chartgpu/chartgpu` package (useful for testing changes across both repositories):
236246

237247
```bash
238-
# 1. Link the chartgpu package from the sibling repo
248+
# 1. Link the @chartgpu/chartgpu package from the sibling repo
239249
cd ../chart-gpu
240250
npm link
241251

242-
# 2. Link chartgpu into this project
252+
# 2. Link @chartgpu/chartgpu into this project
243253
cd ../chartgpu-react
244-
npm link chartgpu
254+
npm link @chartgpu/chartgpu
245255

246256
# 3. Build and run - will use the linked local package
247257
npm run build
248258
npm run dev
249259
```
250260

251-
**Note:** After linking, `npm run build` and `npm run dev` will resolve imports to your local `chartgpu` package instead of the published version. This allows you to test changes in both repos simultaneously.
261+
**Note:** After linking, `npm run build` and `npm run dev` will resolve imports to your local `@chartgpu/chartgpu` package instead of the published version. This allows you to test changes in both repos simultaneously.
252262

253263
To unlink and return to the published package:
254264

255265
```bash
256-
npm unlink chartgpu
266+
npm unlink @chartgpu/chartgpu
257267
npm install
258268
```
259269

@@ -267,13 +277,25 @@ import type {
267277
ChartGPUOptions,
268278
ChartGPUEventPayload,
269279
ChartGPUCrosshairMovePayload,
280+
ChartGPUZoomRangeChangePayload,
281+
ChartGPUHitTestResult,
282+
ChartGPUHitTestMatch,
283+
ChartSyncOptions,
270284
AreaSeriesConfig,
271285
LineSeriesConfig,
272286
BarSeriesConfig,
273287
PieSeriesConfig,
274288
ScatterSeriesConfig,
275289
SeriesConfig,
290+
LineStyleConfig,
291+
AreaStyleConfig,
276292
DataPoint,
293+
LegendConfig,
294+
LegendPosition,
295+
AnimationConfig,
296+
TooltipConfig,
297+
TooltipParams,
298+
PerformanceMetrics,
277299
} from 'chartgpu-react';
278300
```
279301

@@ -293,7 +315,7 @@ const checkSupport = async () => {
293315

294316
## Contributing
295317

296-
Issues and pull requests are welcome. If youre planning a larger change, open an issue first so we can discuss direction.
318+
Issues and pull requests are welcome. If you're planning a larger change, open an issue first so we can discuss direction.
297319

298320
## License
299321

docs/API.md

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# API reference (chartgpu-react)
22

3-
This package is a **React wrapper** around the `chartgpu` core library. Most runtime behavior lives in `chartgpu`; this repo primarily provides:
3+
This package is a **React wrapper** around the `@chartgpu/chartgpu` core library. Most runtime behavior lives in `@chartgpu/chartgpu`; this repo primarily provides:
44

55
- A React component (`ChartGPU`) with lifecycle + resize management
66
- A small imperative ref API (`ChartGPUHandle`)
@@ -19,20 +19,20 @@ For an LLM-oriented navigation entrypoint, see [`docs/api/llm-context.md`](./api
1919
### Hooks
2020

2121
- **`useChartGPU(containerRef, options)`** — create/manage an instance imperatively
22-
- **`useConnectCharts([chartA, chartB, ...])`** — keep crosshair/interaction-x in sync
22+
- **`useConnectCharts([chartA, chartB, ...], syncOptions?)`** — keep crosshair/interaction-x in sync (optionally sync zoom)
2323

2424
See [`docs/api/hooks.md`](./api/hooks.md).
2525

26-
### Helper re-exports (from peer dependency `chartgpu`)
26+
### Helper re-exports (from peer dependency `@chartgpu/chartgpu`)
2727

2828
`chartgpu-react` exposes these helpers so you can often import everything from one package:
2929

3030
- `createChart`
3131
- `connectCharts`
3232
- `createAnnotationAuthoring`
3333

34-
- `createChart` / `connectCharts` are re-exported directly from `chartgpu`.
35-
- `createAnnotationAuthoring` is a thin wrapper around `chartgpu`s helper that includes a small fix for `chartgpu@0.2.3`: the upstream authoring context menu hit-testing does not recognize `type: "text"` annotations, so **Edit** may not appear for text notes.
34+
- `createChart` / `connectCharts` are re-exported directly from `@chartgpu/chartgpu`.
35+
- `createAnnotationAuthoring` is a thin wrapper around `@chartgpu/chartgpu`'s helper that patches text-annotation context-menu hit-testing (broken in `chartgpu@0.2.3`). Upstream v0.2.5 fixes this natively; the wrapper is kept for API stability — the patch is harmless when running against v0.2.5+.
3636

3737
```ts
3838
import { connectCharts, createAnnotationAuthoring } from 'chartgpu-react';
@@ -56,13 +56,13 @@ From `src/types.ts`:
5656

5757
- `ChartGPUProps` — props for the `ChartGPU` component
5858
- `ChartGPUHandle` — imperative ref API
59-
- `ChartInstance` — alias for `chartgpu`s `ChartGPUInstance`
59+
- `ChartInstance` — alias for `@chartgpu/chartgpu`'s `ChartGPUInstance`
6060
- `ClickParams`, `MouseOverParams` — aliases for event payloads
6161
- `ZoomRange` — derived from `ChartGPUInstance['getZoomRange']` (non-null range)
6262

63-
### Re-exported core types (from peer dependency `chartgpu`)
63+
### Re-exported core types (from peer dependency `@chartgpu/chartgpu`)
6464

65-
From `src/index.ts`, this package re-exports a curated set of `chartgpu` types so consumers can do:
65+
From `src/index.ts`, this package re-exports a curated set of `@chartgpu/chartgpu` types so consumers can do:
6666

6767
```ts
6868
import type { ChartGPUOptions, ChartGPUInstance, DataPoint } from 'chartgpu-react';
@@ -71,11 +71,18 @@ import type { ChartGPUOptions, ChartGPUInstance, DataPoint } from 'chartgpu-reac
7171
Currently re-exported:
7272

7373
- **Core**: `ChartGPUInstance`, `ChartGPUOptions`
74-
- **Events**: `ChartGPUEventPayload`, `ChartGPUCrosshairMovePayload`
74+
- **Events**: `ChartGPUEventPayload`, `ChartGPUCrosshairMovePayload`, `ChartGPUZoomRangeChangePayload`
75+
- **Hit testing**: `ChartGPUHitTestResult`, `ChartGPUHitTestMatch`
76+
- **Chart sync**: `ChartSyncOptions`
7577
- **Annotation authoring**: `AnnotationAuthoringInstance`, `AnnotationAuthoringOptions`, `AnnotationConfig`
7678
- **Series config**: `AreaSeriesConfig`, `LineSeriesConfig`, `BarSeriesConfig`, `PieSeriesConfig`, `ScatterSeriesConfig`, `CandlestickSeriesConfig`, `SeriesConfig`
79+
- **Style config**: `LineStyleConfig`, `AreaStyleConfig`
7780
- **Data**: `DataPoint`, `OHLCDataPoint`
7881
- **Interaction/zoom**: `DataZoomConfig`
82+
- **Legend**: `LegendConfig`, `LegendPosition`
83+
- **Animation**: `AnimationConfig`
84+
- **Tooltip**: `TooltipConfig`, `TooltipParams`
85+
- **Performance**: `PerformanceMetrics`
7986
- **Themes**: `ThemeConfig`, `ThemeName`
8087
- **Layout**: `AxisConfig`, `GridConfig`
8188

@@ -109,10 +116,10 @@ See [`useChartGPU` docs](./api/hooks.md#usechartgpu).
109116

110117
### 4) Connecting charts (`useConnectCharts` / `connectCharts`)
111118

112-
To sync crosshair / interaction-x across multiple charts, use:
119+
To sync crosshair / interaction-x (and optionally zoom) across multiple charts, use:
113120

114-
- `useConnectCharts([chartA, chartB, ...])` (React-friendly)
115-
- or `connectCharts([chartA, chartB, ...])` (manual)
121+
- `useConnectCharts([chartA, chartB, ...], syncOptions?)` (React-friendly)
122+
- or `connectCharts([chartA, chartB, ...], syncOptions?)` (manual)
116123

117124
See [Chart sync recipe](./recipes/chart-sync.md).
118125

@@ -126,4 +133,3 @@ Step-by-step guides for common use cases:
126133
- [Streaming](./recipes/streaming.md) — realtime data updates with `appendData`
127134
- [dataZoom basics](./recipes/datazoom-basics.md) — zoom and pan with `dataZoom` + `onZoomChange`
128135
- [Scatter density](./recipes/scatter-density.md) — density heatmaps for large scatter datasets
129-

docs/api/chartgpu-component.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The props type is `ChartGPUProps` (defined in `src/types.ts`).
3131
| `onMouseOver` | `(payload: ChartGPUEventPayload) => void` | | Wires to `chart.on('mouseover', ...)`. |
3232
| `onMouseOut` | `(payload: ChartGPUEventPayload) => void` | | Wires to `chart.on('mouseout', ...)`. |
3333
| `onCrosshairMove` | `(payload: ChartGPUCrosshairMovePayload) => void` | | Wires to `chart.on('crosshairMove', ...)`. |
34-
| `onZoomChange` | `(range: ZoomRange) => void` | | Fires when `chart.getZoomRange()` changes (polled every 100ms). |
34+
| `onZoomChange` | `(range: ZoomRange) => void` | | Fires on `zoomRangeChange` event. Also emits the current range once on subscribe (initial hydration). |
3535

3636
## Imperative ref (`ChartGPUHandle`)
3737

@@ -41,6 +41,10 @@ The props type is `ChartGPUProps` (defined in `src/types.ts`).
4141
- `getContainer()`
4242
- `appendData(seriesIndex, newPoints)`
4343
- `setOption(options)`
44+
- `setZoomRange(start, end)`
45+
- `setInteractionX(x, source?)`
46+
- `getInteractionX()`
47+
- `hitTest(e)` — note: React synthetic events require `e.nativeEvent`
4448

4549
See [`ChartGPUHandle`](./chartgpu-handle.md).
4650

@@ -80,10 +84,9 @@ Resize calls are debounced (100ms).
8084

8185
### Zoom change events
8286

83-
If you provide `onZoomChange`, the component polls `chart.getZoomRange()` every 100ms and fires the callback when:
87+
If you provide `onZoomChange`, the component subscribes to the upstream `zoomRangeChange` event and fires the callback whenever the zoom range changes.
8488

85-
- the zoom range transitions from `null` → non-null, or
86-
- `start`/`end` values change.
89+
On subscribe, the component also reads the current zoom range via `getZoomRange()` and fires `onZoomChange` once if the range is non-null. This ensures consumers can hydrate UI state without waiting for user interaction.
8790

8891
If zoom is disabled (`null`), no callback is fired.
8992

docs/api/chartgpu-handle.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@
66
- accessing the container element
77
- streaming/append updates (`appendData`)
88
- replacing options (`setOption`)
9+
- programmatic zoom control (`setZoomRange`)
10+
- programmatic crosshair/tooltip (`setInteractionX`, `getInteractionX`)
11+
- hit testing (`hitTest`)
912

1013
Related:
1114

1215
- [`ChartGPU` component](./chartgpu-component.md)
1316
- [Streaming recipe](../recipes/streaming.md)
1417
- [Annotation authoring recipe](../recipes/annotation-authoring.md)
18+
- [dataZoom basics](../recipes/datazoom-basics.md)
1519
- LLM entrypoint: [`llm-context.md`](./llm-context.md)
1620

1721
## Import
@@ -25,7 +29,7 @@ import type { ChartGPUHandle } from 'chartgpu-react';
2529

2630
### `getChart(): ChartGPUInstance | null`
2731

28-
Returns the underlying `chartgpu` instance once initialized, otherwise `null`.
32+
Returns the underlying `@chartgpu/chartgpu` instance once initialized, otherwise `null`.
2933

3034
Notes:
3135

@@ -53,6 +57,49 @@ Replaces the chart options, delegating to `ChartGPUInstance.setOption(options)`.
5357

5458
Important: `setOption` is treated as a **full replacement**, not a partial merge.
5559

60+
### `setZoomRange(start: number, end: number): void`
61+
62+
Programmatically sets the zoom range in percent-space.
63+
64+
- **`start`**: start of zoom range (0–100).
65+
- **`end`**: end of zoom range (0–100).
66+
67+
No-op when zoom is disabled on the chart (i.e. no `dataZoom` configured).
68+
69+
### `setInteractionX(x: number | null, source?: unknown): void`
70+
71+
Programmatically drives the crosshair / tooltip to a domain-space x value. Pass `null` to clear the crosshair.
72+
73+
- **`x`**: domain-space x value, or `null` to clear.
74+
- **`source`** (optional): source identifier, useful for sync disambiguation (e.g. avoiding echo loops with `connectCharts`).
75+
76+
### `getInteractionX(): number | null`
77+
78+
Reads the current crosshair / interaction x in domain units. Returns `null` when the crosshair is inactive.
79+
80+
### `hitTest(e: PointerEvent | MouseEvent): ChartGPUHitTestResult`
81+
82+
Performs hit-testing on a pointer or mouse event. Returns coordinates and any matched chart element.
83+
84+
- **`e`**: a native `PointerEvent` or `MouseEvent` from the chart container.
85+
- **Returns**: `ChartGPUHitTestResult` with pixel coordinates, domain-space coordinates, and an optional match object.
86+
- If the chart is not initialized or disposed, returns a sentinel with `isInGrid: false` and `NaN` coordinates.
87+
88+
**React ergonomics note**: React synthetic events (`React.PointerEvent`, `React.MouseEvent`) are not the same as native DOM events. Pass `e.nativeEvent` instead:
89+
90+
```tsx
91+
<div onPointerDown={(e) => {
92+
const result = chartRef.current?.hitTest(e.nativeEvent);
93+
// ...
94+
}} />
95+
```
96+
97+
Import the result type if needed:
98+
99+
```ts
100+
import type { ChartGPUHitTestResult } from 'chartgpu-react';
101+
```
102+
56103
## Example: streaming with `appendData`
57104

58105
```tsx
@@ -98,4 +145,3 @@ export function StreamingCandles() {
98145
return <ChartGPU ref={ref} options={options} style={{ height: 420 }} theme="dark" />;
99146
}
100147
```
101-

0 commit comments

Comments
 (0)