blazeplot 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +439 -187
- package/dist/Chart-BW9JaHs6.js +2903 -0
- package/dist/Chart-BW9JaHs6.js.map +1 -0
- package/dist/OverlayUtils-Cw1o8UH-.js +35 -0
- package/dist/OverlayUtils-Cw1o8UH-.js.map +1 -0
- package/dist/core/SeriesStore.d.ts +2 -0
- package/dist/core/SeriesStore.d.ts.map +1 -1
- package/dist/core/UniformRingBuffer.d.ts +67 -0
- package/dist/core/UniformRingBuffer.d.ts.map +1 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/types.d.ts +5 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +153 -2304
- package/dist/index.js.map +1 -1
- package/dist/interaction/AxisController.d.ts +45 -3
- package/dist/interaction/AxisController.d.ts.map +1 -1
- package/dist/interaction/index.d.ts +1 -0
- package/dist/interaction/index.d.ts.map +1 -1
- package/dist/linked.d.ts +3 -0
- package/dist/linked.d.ts.map +1 -0
- package/dist/linked.js +64 -0
- package/dist/linked.js.map +1 -0
- package/dist/plugins/crosshair.d.ts +3 -0
- package/dist/plugins/crosshair.d.ts.map +1 -0
- package/dist/plugins/crosshair.js +192 -0
- package/dist/plugins/crosshair.js.map +1 -0
- package/dist/plugins/interactions.js +87 -65
- package/dist/plugins/interactions.js.map +1 -1
- package/dist/plugins/navigator.d.ts +3 -0
- package/dist/plugins/navigator.d.ts.map +1 -0
- package/dist/plugins/navigator.js +147 -0
- package/dist/plugins/navigator.js.map +1 -0
- package/dist/plugins/selection.d.ts +3 -0
- package/dist/plugins/selection.d.ts.map +1 -0
- package/dist/plugins/selection.js +144 -0
- package/dist/plugins/selection.js.map +1 -0
- package/dist/plugins/tooltip.js +29 -45
- package/dist/plugins/tooltip.js.map +1 -1
- package/dist/react.d.ts +14 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +30 -0
- package/dist/react.js.map +1 -0
- package/dist/ui/Chart.d.ts +79 -1
- package/dist/ui/Chart.d.ts.map +1 -1
- package/dist/ui/ChartLayout.d.ts +10 -0
- package/dist/ui/ChartLayout.d.ts.map +1 -1
- package/dist/ui/Crosshair.d.ts +60 -0
- package/dist/ui/Crosshair.d.ts.map +1 -0
- package/dist/ui/Interactions.d.ts.map +1 -1
- package/dist/ui/LinkedCharts.d.ts +23 -0
- package/dist/ui/LinkedCharts.d.ts.map +1 -0
- package/dist/ui/Navigator.d.ts +32 -0
- package/dist/ui/Navigator.d.ts.map +1 -0
- package/dist/ui/OverlayUtils.d.ts +17 -0
- package/dist/ui/OverlayUtils.d.ts.map +1 -0
- package/dist/ui/Selection.d.ts +64 -0
- package/dist/ui/Selection.d.ts.map +1 -0
- package/dist/ui/Tooltip.d.ts.map +1 -1
- package/dist/ui/theme.d.ts +12 -0
- package/dist/ui/theme.d.ts.map +1 -1
- package/package.json +35 -5
package/README.md
CHANGED
|
@@ -21,21 +21,23 @@ bun install blazeplot
|
|
|
21
21
|
|
|
22
22
|
## Quick start
|
|
23
23
|
|
|
24
|
+
A chart only needs a host element. For regular arrays, wrap your data in a `StaticDataset`; `capacity` is only needed when you want a streaming ring buffer.
|
|
25
|
+
|
|
24
26
|
```html
|
|
25
27
|
<div id="chart" style="width:100%;height:400px"></div>
|
|
26
28
|
|
|
27
29
|
<script type="module">
|
|
28
|
-
import { Chart } from "blazeplot";
|
|
30
|
+
import { Chart, StaticDataset } from "blazeplot";
|
|
29
31
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
+
const el = document.getElementById("chart");
|
|
33
|
+
if (!el) throw new Error("Missing #chart element");
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Float32Array.from({ length: 1000 }, (_, i) => Math.sin(i * 0.02)),
|
|
36
|
-
);
|
|
35
|
+
const x = Array.from({ length: 1000 }, (_, i) => i);
|
|
36
|
+
const y = x.map((value) => Math.sin(value * 0.02));
|
|
37
37
|
|
|
38
|
-
chart
|
|
38
|
+
const chart = new Chart(el);
|
|
39
|
+
chart.addLine({ dataset: new StaticDataset(x, y), name: "sine" });
|
|
40
|
+
chart.setViewport({ xMin: x[0], xMax: x[x.length - 1], yMin: -1.5, yMax: 1.5 });
|
|
39
41
|
chart.start();
|
|
40
42
|
</script>
|
|
41
43
|
```
|
|
@@ -55,186 +57,423 @@ bun install blazeplot
|
|
|
55
57
|
| **Benchmark overlay** | Built-in fps, frame time, vertex count, draw calls. |
|
|
56
58
|
| **ResizeObserver** | Automatic DPR-aware canvas sizing. |
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
### `Chart`
|
|
61
|
-
|
|
62
|
-
| Signature | Description |
|
|
63
|
-
|---|---|
|
|
64
|
-
| `new Chart(container, options?)` | Create a chart inside an HTML container element. The chart owns the plot canvas and axis layout. |
|
|
65
|
-
| `chart.addSeries(config, style?)` | Add a data series. Returns `SeriesStore`. |
|
|
66
|
-
| `chart.addLine(config, style?)` / `addArea` / `addScatter` / `addBar` / `addOhlc` / `addCandlestick` | Typed helpers that set the series mode for you. `config.yAxis: "right"` maps a series to the secondary Y axis. |
|
|
67
|
-
| `chart.removeSeries(series)` | Remove a previously added series. |
|
|
68
|
-
| `chart.setViewport({ xMin, xMax, yMin, yMax })` | Set the visible data range on both Y axes and the shared X range. |
|
|
69
|
-
| `chart.setYViewport("left" | "right", { yMin, yMax })` | Set one Y-axis viewport while preserving the shared X range. |
|
|
70
|
-
| `chart.getViewport(yAxis?)` | Return the current visible data range for `"left"` or `"right"` Y axis. |
|
|
71
|
-
| `chart.pan(intent)` / `chart.zoom(intent)` | Plugin-facing camera interaction helpers. |
|
|
72
|
-
| `chart.clientToData(clientX, clientY, yAxis?)` / `chart.dataToPlot(x, y, yAxis?)` | Convert between client/plot coordinates and data coordinates for the selected Y axis. |
|
|
73
|
-
| `chart.resize(dpr?)` | Resize the internal plot canvas to match its CSS size × DPR. |
|
|
74
|
-
| `chart.start()` | Start the render loop (rAF). |
|
|
75
|
-
| `chart.stop()` | Stop the render loop. |
|
|
76
|
-
| `chart.canvas` | Read-only access to the internal plot canvas. |
|
|
77
|
-
| `chart.xAxisElement` / `chart.yAxisElement` | Plugin-facing access to outside axis gutter elements. |
|
|
78
|
-
| `chart.theme` | Resolved theme values used by the chart and built-in plugins. |
|
|
79
|
-
| `chart.getFrameStats(target?)` | Copy per-frame benchmark counters into a reusable object. |
|
|
80
|
-
| `chart.getSeriesState()` | Return public series metadata/state for plugins or custom UI. |
|
|
81
|
-
| `chart.setSeriesVisible(series, visible)` | Toggle visibility and notify series-state subscribers. |
|
|
82
|
-
| `chart.pick(clientX, clientY, options?)` | Raw-data hit test. Supports `mode: "nearest-x" | "nearest-point"`, `group: "x" | "none"`, and `maxDistancePx`; returned items include actual sample X/Y and plot/client coordinates for highlights. |
|
|
83
|
-
| `chart.subscribe("hover", cb)` / `chart.subscribe("serieschange", cb)` | Subscribe to hover or series state changes. Returns an unsubscribe function. |
|
|
84
|
-
| `await chart.screenshot(options?)` | Export the full chart as an image `Blob`, including the WebGL plot and built-in DOM text overlays. |
|
|
85
|
-
| `chart.dispose()` | Dispose GPU resources, observers, input handlers, and owned DOM layout. |
|
|
86
|
-
|
|
87
|
-
### `ChartOptions`
|
|
88
|
-
|
|
89
|
-
| Property | Default | Description |
|
|
90
|
-
|---|---|---|
|
|
91
|
-
| `viewportPolicy?` | — | Optional `beforeRender` viewport hook. Pass the same policy to `interactionsPlugin({ viewportPolicy })` for pan/zoom hooks. |
|
|
92
|
-
| `hover?` | `{ mode: "nearest-x", group: "x" }` | Default hover picking behavior. `mode` can be `"nearest-x"` or `"nearest-point"`; `group: "x"` reports one item per visible series at the selected X, while `group: "none"` reports only the selected point. |
|
|
93
|
-
| `plugins?` | `[]` | Optional `ChartPlugin` instances, e.g. `legendPlugin()` and `tooltipPlugin()`. |
|
|
94
|
-
| `theme?` | built-in dark theme | Override chart, axis, palette, legend, and tooltip colors/fonts. |
|
|
95
|
-
| `grid?` | `true` | Show grid lines. |
|
|
96
|
-
| `gridStyle?` | `{ color: theme.gridColor }` | Grid line color and width; overrides the theme grid color. |
|
|
97
|
-
| `axes?` | `true` | Show axis tick labels. `true`/`false`, or per-axis `{ x?: boolean \| AxisConfig, y?: boolean \| AxisConfig, y2?: boolean \| AxisConfig }`. `y2` is the right-side secondary Y axis and is hidden by default. |
|
|
98
|
-
|
|
99
|
-
### `ChartTheme`
|
|
100
|
-
|
|
101
|
-
```css
|
|
102
|
-
:root {
|
|
103
|
-
--plot-bg: #050816;
|
|
104
|
-
--plot-grid: rgb(148 163 184 / 0.22);
|
|
105
|
-
--plot-axis: #cbd5e1;
|
|
106
|
-
--series-a: #38bdf8;
|
|
107
|
-
--series-b: oklch(70% 0.19 22);
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
```ts
|
|
112
|
-
new Chart(container, {
|
|
113
|
-
theme: {
|
|
114
|
-
backgroundColor: "var(--plot-bg)",
|
|
115
|
-
gridColor: "var(--plot-grid)",
|
|
116
|
-
axisColor: "var(--plot-axis)",
|
|
117
|
-
seriesColors: ["var(--series-a)", "var(--series-b)"],
|
|
118
|
-
tooltipBackgroundColor: "rgb(4 8 16 / 0.85)",
|
|
119
|
-
legendBackgroundColor: "rgb(4 8 16 / 0.85)",
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
WebGL-facing colors (`backgroundColor`, `gridColor`, `seriesColors`) accept either normalized RGBA tuples (`[r,g,b,a]`) or CSS colors, including CSS variables inherited by the chart container. BlazePlot resolves CSS colors internally to WebGL-compatible RGBA floats while preserving CSS strings for DOM styling where appropriate. Per-series styles and plugin options still override theme defaults.
|
|
125
|
-
|
|
126
|
-
### `AxisConfig`
|
|
127
|
-
|
|
128
|
-
| Property | Default | Description |
|
|
129
|
-
|---|---|---|
|
|
130
|
-
| `visible?` | `true` | Show this axis. |
|
|
131
|
-
| `position?` | `"inside"` | `"inside"` draws labels over the plot; `"outside"` reserves a real DOM gutter and shrinks the plot canvas. |
|
|
132
|
-
|
|
133
|
-
```ts
|
|
134
|
-
// X labels outside (bottom gutter), left Y inside, right Y outside.
|
|
135
|
-
const chart = new Chart(canvas, {
|
|
136
|
-
axes: { x: { position: "outside" }, y: true, y2: { position: "outside" } }
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
chart.addLine({ capacity: 10_000, yAxis: "left" });
|
|
140
|
-
chart.addLine({ capacity: 10_000, yAxis: "right" });
|
|
141
|
-
chart.setYViewport("right", { yMin: 0, yMax: 100 });
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### `ChartFrameStats`
|
|
60
|
+
<!-- README_DOCS_START -->
|
|
61
|
+
## API reference
|
|
145
62
|
|
|
146
|
-
|
|
147
|
-
|---|---|
|
|
148
|
-
| `fps` | Instantaneous render-loop FPS. |
|
|
149
|
-
| `frameMs` | Milliseconds spent in `render()`. |
|
|
150
|
-
| `pointsRendered` | Number of vertices drawn this frame. |
|
|
151
|
-
| `drawCalls` | Number of GPU draw calls this frame. |
|
|
152
|
-
| `uploadBytes` | Bytes uploaded to GPU this frame. |
|
|
153
|
-
| `renderMode` | `"none"` / `"raw"` / `"minmax"` / `"points"` / `"bars"` / `"area"` / `"mixed"`. |
|
|
154
|
-
|
|
155
|
-
### Plugins
|
|
156
|
-
|
|
157
|
-
```js
|
|
158
|
-
import { Chart } from "blazeplot";
|
|
159
|
-
import { interactionsPlugin } from "blazeplot/plugins/interactions";
|
|
160
|
-
import { legendPlugin } from "blazeplot/plugins/legend";
|
|
161
|
-
import { tooltipPlugin } from "blazeplot/plugins/tooltip";
|
|
162
|
-
import { annotationsPlugin } from "blazeplot/plugins/annotations";
|
|
163
|
-
|
|
164
|
-
const chart = new Chart(container, {
|
|
165
|
-
hover: { mode: "nearest-x", group: "x" },
|
|
166
|
-
plugins: [
|
|
167
|
-
interactionsPlugin({ axis: "xy" }),
|
|
168
|
-
annotationsPlugin({
|
|
169
|
-
annotations: [
|
|
170
|
-
{ type: "y-line", y: 0, label: "baseline" },
|
|
171
|
-
{ type: "x-range", xMin: 10, xMax: 20, label: "event" },
|
|
172
|
-
{ type: "point", x: 42, y: 1.2, shape: "diamond", label: "marker" },
|
|
173
|
-
],
|
|
174
|
-
}),
|
|
175
|
-
legendPlugin(),
|
|
176
|
-
tooltipPlugin({ mode: "nearest-point", group: "none", maxDistancePx: 24 }),
|
|
177
|
-
],
|
|
178
|
-
});
|
|
179
|
-
```
|
|
63
|
+
This section is generated by `bun run docs:readme` from TypeScript declaration files and JSDoc comments. Do not edit it by hand.
|
|
180
64
|
|
|
181
|
-
|
|
65
|
+
- [Quick start](#quick-start)
|
|
66
|
+
- [Features](#features)
|
|
67
|
+
- [Architecture](#architecture)
|
|
68
|
+
- [Development](#development)
|
|
69
|
+
- [Roadmap](ROADMAP.md)
|
|
70
|
+
- [Changelog for v0.3.1](changelogs/v0.3.1.md)
|
|
182
71
|
|
|
183
|
-
###
|
|
72
|
+
### Package entry points
|
|
184
73
|
|
|
185
|
-
|
|
|
74
|
+
| Import | Contents |
|
|
186
75
|
|---|---|
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
|
206
|
-
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
209
|
-
| `
|
|
210
|
-
| `
|
|
211
|
-
| `
|
|
212
|
-
| `
|
|
213
|
-
| `
|
|
214
|
-
| `
|
|
215
|
-
| `
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
`
|
|
220
|
-
|
|
221
|
-
`
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
76
|
+
| `blazeplot` | Core chart, data, interaction, rendering types, and low-level primitives. |
|
|
77
|
+
| `blazeplot/react` | React wrapper component and hooks. |
|
|
78
|
+
| `blazeplot/linked` | Linked chart layout helpers. |
|
|
79
|
+
| `blazeplot/plugins/legend` | Built-in legend plugin. |
|
|
80
|
+
| `blazeplot/plugins/tooltip` | Built-in tooltip plugin. |
|
|
81
|
+
| `blazeplot/plugins/interactions` | Built-in pan, zoom, axis interaction, and reset plugin. |
|
|
82
|
+
| `blazeplot/plugins/annotations` | Built-in annotation overlay plugin. |
|
|
83
|
+
| `blazeplot/plugins/selection` | Built-in brush/range selection plugin. |
|
|
84
|
+
| `blazeplot/plugins/crosshair` | Built-in crosshair and ruler plugin. |
|
|
85
|
+
| `blazeplot/plugins/navigator` | Built-in overview/navigator plugin. |
|
|
86
|
+
|
|
87
|
+
### Selected generated declarations
|
|
88
|
+
|
|
89
|
+
These member tables are generated from TypeScript declarations.
|
|
90
|
+
|
|
91
|
+
<details>
|
|
92
|
+
<summary>class Chart</summary>
|
|
93
|
+
|
|
94
|
+
| Member |
|
|
95
|
+
|---|
|
|
96
|
+
| `constructor(target: HTMLElement, options?: ChartOptions)` |
|
|
97
|
+
| `get canvas(): HTMLCanvasElement` |
|
|
98
|
+
| `get rootElement(): HTMLElement` |
|
|
99
|
+
| `get plotElement(): HTMLElement` |
|
|
100
|
+
| `get xAxisElement(): HTMLElement` |
|
|
101
|
+
| `get yAxisElement(): HTMLElement` |
|
|
102
|
+
| `get y2AxisElement(): HTMLElement` |
|
|
103
|
+
| `get theme(): ResolvedChartTheme` |
|
|
104
|
+
| `getWebGLContext(): WebGL2RenderingContext \\| null` |
|
|
105
|
+
| `getCamera(yAxis?: SeriesYAxis): Camera2D` |
|
|
106
|
+
| `dataToPlot(x: number, y: number, yAxis?: SeriesYAxis): [ number, number ]` |
|
|
107
|
+
| `clientToData(clientX: number, clientY: number, yAxis?: SeriesYAxis): [ number, number ] \\| null` |
|
|
108
|
+
| `getViewport(yAxis?: SeriesYAxis): Viewport` |
|
|
109
|
+
| `pan(intent: PanIntent): void` |
|
|
110
|
+
| `zoom(intent: ZoomIntent): void` |
|
|
111
|
+
| `addSeries(config: SeriesConfig, style?: Partial<SeriesStyle>): SeriesStore` |
|
|
112
|
+
| `addLine(config: TypedSeriesConfig, style?: Partial<SeriesStyle>): SeriesStore` |
|
|
113
|
+
| `addArea(config: TypedSeriesConfig, style?: Partial<SeriesStyle>): SeriesStore` |
|
|
114
|
+
| `addScatter(config: TypedSeriesConfig, style?: Partial<SeriesStyle>): SeriesStore` |
|
|
115
|
+
| `addBar(config: TypedSeriesConfig, style?: Partial<SeriesStyle>): SeriesStore` |
|
|
116
|
+
| `addOhlc(config: TypedSeriesConfig, style?: Partial<SeriesStyle>): SeriesStore` |
|
|
117
|
+
| `addCandlestick(config: TypedSeriesConfig, style?: Partial<SeriesStyle>): SeriesStore` |
|
|
118
|
+
| `removeSeries(series: SeriesStore): boolean` |
|
|
119
|
+
| `setSeriesVisible(series: SeriesStore, visible: boolean): boolean` |
|
|
120
|
+
| `getSeriesState(): ChartSeriesState[]` |
|
|
121
|
+
| `setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number; }): void` |
|
|
122
|
+
| `setYViewport(yAxis: SeriesYAxis, v: { yMin?: number; yMax?: number; }): void` |
|
|
123
|
+
| `resize(dpr?: number): boolean` |
|
|
124
|
+
| `getFrameStats(target?: ChartFrameStats): ChartFrameStats` |
|
|
125
|
+
| `getHoverState(): ChartHoverState \\| null` |
|
|
126
|
+
| `setLayoutReservation(id: string, reservation: ChartLayoutReservation \\| null): void` |
|
|
127
|
+
| `subscribe(event: "hover", callback: (state: ChartHoverState \\| null) => void): () => void` |
|
|
128
|
+
| `subscribe(event: "serieschange", callback: () => void): () => void` |
|
|
129
|
+
| `subscribe(event: "themechange", callback: () => void): () => void` |
|
|
130
|
+
| `subscribe(event: "render", callback: (chart: Chart) => void): () => void` |
|
|
131
|
+
| `subscribe(event: "viewportchange", callback: (event: ChartViewportChangeEvent) => void): () => void` |
|
|
132
|
+
| `subscribe(event: "select", callback: (event: ChartSelectEvent) => void): () => void` |
|
|
133
|
+
| `subscribe(event: "seriesclick", callback: (event: ChartSeriesClickEvent) => void): () => void` |
|
|
134
|
+
| `subscribe(event: ChartPointerEventType, callback: (event: ChartPointerEventState) => void): () => void` |
|
|
135
|
+
| `emitSelect(selection: unknown): void` |
|
|
136
|
+
| `setTheme(theme?: ChartTheme): void` |
|
|
137
|
+
| `setGridVisible(visible: boolean): void` |
|
|
138
|
+
| `getGridVisible(): boolean` |
|
|
139
|
+
| `setAxes(axes: ChartOptions["axes"]): void` |
|
|
140
|
+
| `pick(clientX: number, clientY: number, options?: ChartPickOptions): ChartHoverState \\| null` |
|
|
141
|
+
| `screenshot(options?: ChartScreenshotOptions): Promise<Blob>` |
|
|
142
|
+
| `start(): void` |
|
|
143
|
+
| `stop(): void` |
|
|
144
|
+
| `dispose(): void` |
|
|
145
|
+
|
|
146
|
+
</details>
|
|
147
|
+
|
|
148
|
+
<details>
|
|
149
|
+
<summary>interface ChartOptions</summary>
|
|
150
|
+
|
|
151
|
+
| Member |
|
|
152
|
+
|---|
|
|
153
|
+
| `viewportPolicy?: ViewportPolicy` |
|
|
154
|
+
| `grid?: boolean` |
|
|
155
|
+
| `gridStyle?: Partial<SeriesStyle>` |
|
|
156
|
+
| `axes?: boolean \\| { x?: boolean \\| AxisConfig; y?: boolean \\| AxisConfig; y2?: boolean \\| AxisConfig; }` |
|
|
157
|
+
| `title?: string \\| ChartTitleConfig` |
|
|
158
|
+
| `subtitle?: string \\| ChartTitleConfig` |
|
|
159
|
+
| `hover?: ChartPickOptions` |
|
|
160
|
+
| `plugins?: readonly ChartPlugin[]` |
|
|
161
|
+
| `theme?: ChartTheme` |
|
|
162
|
+
|
|
163
|
+
</details>
|
|
164
|
+
|
|
165
|
+
<details>
|
|
166
|
+
<summary>interface ChartTheme</summary>
|
|
167
|
+
|
|
168
|
+
| Member |
|
|
169
|
+
|---|
|
|
170
|
+
| `backgroundColor?: ThemeColor` |
|
|
171
|
+
| `gridColor?: ThemeColor` |
|
|
172
|
+
| `axisColor?: string` |
|
|
173
|
+
| `axisFont?: string` |
|
|
174
|
+
| `seriesColors?: readonly ThemeColor[]` |
|
|
175
|
+
| `tooltipBackgroundColor?: string` |
|
|
176
|
+
| `tooltipTextColor?: string` |
|
|
177
|
+
| `tooltipFont?: string` |
|
|
178
|
+
| `legendBackgroundColor?: string` |
|
|
179
|
+
| `legendBorderColor?: string` |
|
|
180
|
+
| `legendTextColor?: string` |
|
|
181
|
+
| `legendMutedTextColor?: string` |
|
|
182
|
+
| `legendFont?: string` |
|
|
183
|
+
| `titleColor?: string` |
|
|
184
|
+
| `titleFont?: string` |
|
|
185
|
+
| `subtitleColor?: string` |
|
|
186
|
+
| `subtitleFont?: string` |
|
|
187
|
+
| `axisTitleColor?: string` |
|
|
188
|
+
| `axisTitleFont?: string` |
|
|
189
|
+
|
|
190
|
+
</details>
|
|
191
|
+
|
|
192
|
+
<details>
|
|
193
|
+
<summary>interface AxisConfig</summary>
|
|
194
|
+
|
|
195
|
+
| Member |
|
|
196
|
+
|---|
|
|
197
|
+
| `visible?: boolean` |
|
|
198
|
+
| `position?: AxisPosition` |
|
|
199
|
+
| `scale?: AxisScale` |
|
|
200
|
+
| `tickFormat?: AxisTickFormat` |
|
|
201
|
+
| `timezone?: AxisTimeZone` |
|
|
202
|
+
| `title?: string \\| AxisTitleConfig` |
|
|
203
|
+
|
|
204
|
+
</details>
|
|
205
|
+
|
|
206
|
+
<details>
|
|
207
|
+
<summary>class SeriesStore</summary>
|
|
208
|
+
|
|
209
|
+
| Member |
|
|
210
|
+
|---|
|
|
211
|
+
| `config: SeriesConfig` |
|
|
212
|
+
| `style: SeriesStyle` |
|
|
213
|
+
| `constructor(dataset: Dataset, config: SeriesConfig, style: SeriesStyle)` |
|
|
214
|
+
| `get hasLOD(): boolean` |
|
|
215
|
+
| `get dirty(): boolean` |
|
|
216
|
+
| `get length(): number` |
|
|
217
|
+
| `get visible(): boolean` |
|
|
218
|
+
| `setVisible(visible: boolean): void` |
|
|
219
|
+
| `append(x: ArrayLike<number>, y: ArrayLike<number>): void` |
|
|
220
|
+
| `appendY(y: ArrayLike<number>): void` |
|
|
221
|
+
| `markDirty(): void` |
|
|
222
|
+
| `clear(): void` |
|
|
223
|
+
| `rebuildPyramid(): void` |
|
|
224
|
+
| `query(viewport: Viewport, pixelWidth: number): LODView` |
|
|
225
|
+
| `visibleSampleCount(viewport: Viewport): number` |
|
|
226
|
+
| `sampleAt(index: number): SeriesSample \\| null` |
|
|
227
|
+
| `nearestSampleByX(x: number, viewport?: Viewport): SeriesSample \\| null` |
|
|
228
|
+
| `nearestSampleByPoint(x: number, y: number, viewport: Viewport, plotWidth: number, plotHeight: number, maxDistancePx?: number): SeriesSample \\| null` |
|
|
229
|
+
| `copyRawVisible(viewport: Viewport, target: Float32Array, maxPoints: number, xOrigin?: number): number` |
|
|
230
|
+
| `copyScatterVisible(viewport: Viewport, target: Float32Array, maxPoints: number, pixelWidth: number, pixelHeight: number, pointSize: number, xOrigin?: number): number` |
|
|
231
|
+
| `copyScatterRange(start: number, end: number, viewport: Viewport, target: Float32Array, maxPoints: number, xOrigin?: number, pixelHeight?: number, pointSize?: number): number` |
|
|
232
|
+
| `copyRawVisibleClipped(viewport: Viewport, target: Float32Array, maxPoints: number, xOrigin?: number): number` |
|
|
233
|
+
| `copyRawVisibleClipSpace(viewport: Viewport, target: Float32Array, maxPoints: number): number` |
|
|
234
|
+
| `copyRawRange(start: number, end: number, target: Float32Array, maxPoints: number, xOrigin?: number): number` |
|
|
235
|
+
| `copyAreaVisible(viewport: Viewport, target: Float32Array, maxPoints: number, baseline?: number, xOrigin?: number): number` |
|
|
236
|
+
| `copyAreaRange(start: number, end: number, target: Float32Array, maxPoints: number, baseline?: number, xOrigin?: number): number` |
|
|
237
|
+
| `copyMinMaxVisible(viewport: Viewport, target: Float32Array, maxSegments: number, xOrigin?: number): number` |
|
|
238
|
+
| `copyMinMaxInstanced(viewport: Viewport, target: Float32Array, maxSegments: number, xOrigin?: number): number` |
|
|
239
|
+
| `copyOhlcRange(start: number, end: number, target: Float32Array, maxCandles: number, tickWidth: number, xOrigin?: number): number` |
|
|
240
|
+
| `copyOhlcTuplesRange(start: number, end: number, target: Float32Array, maxCandles: number, xOrigin?: number): number` |
|
|
241
|
+
| `visibleIndexRange(viewport: Viewport \\| undefined, outerPadding?: number): { start: number; end: number; }` |
|
|
242
|
+
|
|
243
|
+
</details>
|
|
244
|
+
|
|
245
|
+
<details>
|
|
246
|
+
<summary>interface SeriesConfig</summary>
|
|
247
|
+
|
|
248
|
+
| Member |
|
|
249
|
+
|---|
|
|
250
|
+
| `mode: SeriesMode` |
|
|
251
|
+
| `capacity?: number` |
|
|
252
|
+
| `downsample?: LODStrategy` |
|
|
253
|
+
| `overflow?: BufferOverflowStrategy` |
|
|
254
|
+
| `dataset?: Dataset` |
|
|
255
|
+
| `yAxis?: SeriesYAxis` |
|
|
256
|
+
| `id?: string` |
|
|
257
|
+
| `name?: string` |
|
|
258
|
+
|
|
259
|
+
</details>
|
|
260
|
+
|
|
261
|
+
<details>
|
|
262
|
+
<summary>interface SeriesStyle</summary>
|
|
263
|
+
|
|
264
|
+
| Member |
|
|
265
|
+
|---|
|
|
266
|
+
| `color: readonly [ number, number, number, number ]` |
|
|
267
|
+
| `lineWidth: number` |
|
|
268
|
+
| `pointSize?: number` |
|
|
269
|
+
| `barWidth?: number` |
|
|
270
|
+
| `baseline?: number` |
|
|
271
|
+
| `fillColor?: readonly [ number, number, number, number ]` |
|
|
272
|
+
| `tickWidth?: number` |
|
|
273
|
+
| `upColor?: readonly [ number, number, number, number ]` |
|
|
274
|
+
| `downColor?: readonly [ number, number, number, number ]` |
|
|
275
|
+
| `wickColor?: readonly [ number, number, number, number ]` |
|
|
276
|
+
|
|
277
|
+
</details>
|
|
278
|
+
|
|
279
|
+
<details>
|
|
280
|
+
<summary>class UniformRingBuffer</summary>
|
|
281
|
+
|
|
282
|
+
| Member |
|
|
283
|
+
|---|
|
|
284
|
+
| `capacity: number` |
|
|
285
|
+
| `xStep: number` |
|
|
286
|
+
| `constructor(capacity: number, options?: UniformRingBufferOptions)` |
|
|
287
|
+
| `get length(): number` |
|
|
288
|
+
| `get range(): TimeRange \\| null` |
|
|
289
|
+
| `push(x: number, y: number): void` |
|
|
290
|
+
| `append(x: ArrayLike<number>, y: ArrayLike<number>): void` |
|
|
291
|
+
| `appendY(y: ArrayLike<number>): void` |
|
|
292
|
+
| `clear(): void` |
|
|
293
|
+
| `getX(index: number): number` |
|
|
294
|
+
| `getY(index: number): number` |
|
|
295
|
+
| `lowerBoundX(x: number): number` |
|
|
296
|
+
| `upperBoundX(x: number): number` |
|
|
297
|
+
| `rangeMinMaxY(start: number, end: number): { minY: number; maxY: number; } \\| null` |
|
|
298
|
+
| `copyVisibleSamples(viewport: Viewport, target: Float32Array, maxPoints: number, layout: SampleLayout, baseline: number, xOrigin: number): number` |
|
|
299
|
+
| `copySamplesRange(start: number, end: number, target: Float32Array, maxPoints: number, layout: SampleLayout, baseline: number, xOrigin: number): number` |
|
|
300
|
+
| `copyMinMaxSegments(viewport: Viewport, target: Float32Array, maxSegments: number, layout: MinMaxLayout, xOrigin: number): number` |
|
|
301
|
+
|
|
302
|
+
</details>
|
|
303
|
+
|
|
304
|
+
<details>
|
|
305
|
+
<summary>class RingBuffer</summary>
|
|
306
|
+
|
|
307
|
+
| Member |
|
|
308
|
+
|---|
|
|
309
|
+
| `capacity: number` |
|
|
310
|
+
| `constructor(capacity: number, options?: RingBufferOptions)` |
|
|
311
|
+
| `get length(): number` |
|
|
312
|
+
| `get range(): TimeRange \\| null` |
|
|
313
|
+
| `push(x: number, y: number): void` |
|
|
314
|
+
| `append(x: ArrayLike<number>, y: ArrayLike<number>): void` |
|
|
315
|
+
| `get(index: number): { x: number; y: number; } \\| null` |
|
|
316
|
+
| `getX(index: number): number` |
|
|
317
|
+
| `getY(index: number): number` |
|
|
318
|
+
| `lowerBoundX(x: number): number` |
|
|
319
|
+
| `upperBoundX(x: number): number` |
|
|
320
|
+
| `rangeMinMaxY(start: number, end: number): { minY: number; maxY: number; } \\| null` |
|
|
321
|
+
| `clear(): void` |
|
|
322
|
+
|
|
323
|
+
</details>
|
|
324
|
+
|
|
325
|
+
<details>
|
|
326
|
+
<summary>class StaticDataset</summary>
|
|
327
|
+
|
|
328
|
+
| Member |
|
|
329
|
+
|---|
|
|
330
|
+
| `constructor(xData: ArrayLike<number>, yData: ArrayLike<number>)` |
|
|
331
|
+
| `get length(): number` |
|
|
332
|
+
| `get range(): TimeRange \\| null` |
|
|
333
|
+
| `getX(index: number): number` |
|
|
334
|
+
| `getY(index: number): number` |
|
|
335
|
+
| `lowerBoundX(x: number): number` |
|
|
336
|
+
| `upperBoundX(x: number): number` |
|
|
337
|
+
|
|
338
|
+
</details>
|
|
339
|
+
|
|
340
|
+
<details>
|
|
341
|
+
<summary>class OhlcRingBuffer</summary>
|
|
342
|
+
|
|
343
|
+
| Member |
|
|
344
|
+
|---|
|
|
345
|
+
| `capacity: number` |
|
|
346
|
+
| `constructor(capacity: number, options?: OhlcRingBufferOptions)` |
|
|
347
|
+
| `get length(): number` |
|
|
348
|
+
| `get range(): TimeRange \\| null` |
|
|
349
|
+
| `push(x: number, open: number, high: number, low: number, close: number): void` |
|
|
350
|
+
| `append(x: ArrayLike<number>, open: ArrayLike<number>, high: ArrayLike<number>, low: ArrayLike<number>, close: ArrayLike<number>): void` |
|
|
351
|
+
| `clear(): void` |
|
|
352
|
+
| `getX(index: number): number` |
|
|
353
|
+
| `getY(index: number): number` |
|
|
354
|
+
| `getOpen(index: number): number` |
|
|
355
|
+
| `getHigh(index: number): number` |
|
|
356
|
+
| `getLow(index: number): number` |
|
|
357
|
+
| `getClose(index: number): number` |
|
|
358
|
+
| `lowerBoundX(x: number): number` |
|
|
359
|
+
| `upperBoundX(x: number): number` |
|
|
360
|
+
|
|
361
|
+
</details>
|
|
362
|
+
|
|
363
|
+
<details>
|
|
364
|
+
<summary>interface Dataset</summary>
|
|
365
|
+
|
|
366
|
+
| Member |
|
|
367
|
+
|---|
|
|
368
|
+
| `length: number` |
|
|
369
|
+
| `range: TimeRange \\| null` |
|
|
370
|
+
| `getX(index: number): number` |
|
|
371
|
+
| `getY(index: number): number` |
|
|
372
|
+
| `lowerBoundX(x: number): number` |
|
|
373
|
+
| `upperBoundX(x: number): number` |
|
|
374
|
+
|
|
375
|
+
</details>
|
|
376
|
+
|
|
377
|
+
<details>
|
|
378
|
+
<summary>interface ViewportPolicy</summary>
|
|
379
|
+
|
|
380
|
+
| Member |
|
|
381
|
+
|---|
|
|
382
|
+
| `beforePan(camera: Camera2D, intent: PanIntent): PanIntent \\| null` |
|
|
383
|
+
| `beforeZoom(camera: Camera2D, intent: ZoomIntent): ZoomIntent \\| null` |
|
|
384
|
+
| `beforeRender(camera: Camera2D): void` |
|
|
385
|
+
|
|
386
|
+
</details>
|
|
387
|
+
|
|
388
|
+
### All public exports
|
|
389
|
+
|
|
390
|
+
<details>
|
|
391
|
+
<summary>Generated from <code>dist/index.d.ts</code> after the package build</summary>
|
|
392
|
+
|
|
393
|
+
| Export | Kind | Source | JSDoc summary |
|
|
394
|
+
|---|---|---|---|
|
|
395
|
+
| `AcceleratedDataset` | interface | `./core/types` | Convenience contract for maximum-performance custom datasets. Implement this when a dataset can provide fast exact sample copies, stable viewport sampling, range min/max queries, and renderer-ready min/max buckets. |
|
|
396
|
+
| `AppendableDataset` | interface | `./core/types` | — |
|
|
397
|
+
| `AxisConfig` | interface | `./ui/Chart` | — |
|
|
398
|
+
| `AxisController` | class | `./interaction/AxisController` | — |
|
|
399
|
+
| `AxisControllerAxisOptions` | interface | `./interaction/AxisController` | — |
|
|
400
|
+
| `AxisControllerOptions` | interface | `./interaction/AxisController` | — |
|
|
401
|
+
| `AxisPosition` | type | `./ui/ChartLayout` | — |
|
|
402
|
+
| `AxisRenderTarget` | type | `./interaction/AxisController` | — |
|
|
403
|
+
| `AxisScale` | type | `./interaction/AxisController` | — |
|
|
404
|
+
| `AxisTickFormat` | type | `./interaction/AxisController` | — |
|
|
405
|
+
| `AxisTickFormatter` | type | `./interaction/AxisController` | — |
|
|
406
|
+
| `AxisTimeZone` | type | `./interaction/AxisController` | — |
|
|
407
|
+
| `AxisTitleConfig` | interface | `./ui/Chart` | — |
|
|
408
|
+
| `BufferOverflowStrategy` | type | `./core/types` | — |
|
|
409
|
+
| `BuiltInAxisScale` | type | `./interaction/AxisController` | — |
|
|
410
|
+
| `Camera2D` | class | `./interaction/Camera2D` | — |
|
|
411
|
+
| `Chart` | class | `./ui/Chart` | — |
|
|
412
|
+
| `ChartFrameStats` | interface | `./ui/Chart` | — |
|
|
413
|
+
| `ChartHoverState` | interface | `./ui/Chart` | — |
|
|
414
|
+
| `ChartLayoutReservation` | interface | `./ui/Chart` | — |
|
|
415
|
+
| `ChartOptions` | interface | `./ui/Chart` | — |
|
|
416
|
+
| `ChartPickGroup` | type | `./ui/Chart` | — |
|
|
417
|
+
| `ChartPickItem` | interface | `./ui/Chart` | — |
|
|
418
|
+
| `ChartPickMode` | type | `./ui/Chart` | — |
|
|
419
|
+
| `ChartPickOptions` | interface | `./ui/Chart` | — |
|
|
420
|
+
| `ChartPlugin` | interface | `./ui/Chart` | — |
|
|
421
|
+
| `ChartPluginHandle` | interface | `./ui/Chart` | — |
|
|
422
|
+
| `ChartPointerEventState` | interface | `./ui/Chart` | — |
|
|
423
|
+
| `ChartPointerEventType` | type | `./ui/Chart` | — |
|
|
424
|
+
| `ChartScreenshotOptions` | interface | `./ui/Chart` | — |
|
|
425
|
+
| `ChartSelectEvent` | interface | `./ui/Chart` | — |
|
|
426
|
+
| `ChartSeriesClickEvent` | interface | `./ui/Chart` | — |
|
|
427
|
+
| `ChartSeriesState` | interface | `./ui/Chart` | — |
|
|
428
|
+
| `ChartTheme` | interface | `./ui/theme` | — |
|
|
429
|
+
| `ChartTitleConfig` | interface | `./ui/Chart` | — |
|
|
430
|
+
| `ChartViewportChangeEvent` | interface | `./ui/Chart` | — |
|
|
431
|
+
| `CssColor` | type | `./ui/theme` | — |
|
|
432
|
+
| `CustomAxisScale` | interface | `./interaction/AxisController` | — |
|
|
433
|
+
| `Dataset` | interface | `./core/types` | — |
|
|
434
|
+
| `DEFAULT_CHART_THEME` | const | `./ui/theme` | — |
|
|
435
|
+
| `LODBucket` | interface | `./core/types` | — |
|
|
436
|
+
| `LODStrategy` | type | `./core/types` | — |
|
|
437
|
+
| `LODView` | interface | `./core/types` | — |
|
|
438
|
+
| `MinMaxPyramid` | class | `./core/MinMaxPyramid` | — |
|
|
439
|
+
| `MinMaxSegmentCopyDataset` | interface | `./core/types` | Optional high-performance min/max extraction capability for dense rendering. Implementations can use pyramids, segment trees, database aggregates, or analytic/procedural envelopes to emit renderer-ready min/max buckets. |
|
|
440
|
+
| `MinMaxSegmentLayout` | type | `./core/types` | — |
|
|
441
|
+
| `OhlcDataset` | interface | `./core/types` | — |
|
|
442
|
+
| `OhlcRingBuffer` | class | `./core/OhlcDataset` | — |
|
|
443
|
+
| `OhlcRingBufferOptions` | interface | `./core/OhlcDataset` | — |
|
|
444
|
+
| `PanIntent` | interface | `./interaction/types` | — |
|
|
445
|
+
| `RangeMinMaxDataset` | interface | `./core/types` | — |
|
|
446
|
+
| `RangeSampleCopyDataset` | interface | `./core/types` | Optional high-performance extraction capability for datasets that can copy raw samples without going through repeated getX/getY calls. Implement this for very large datasets, implicit-X datasets, or remote/memory-mapped sources. |
|
|
447
|
+
| `ResolvedChartTheme` | interface | `./ui/theme` | — |
|
|
448
|
+
| `RgbaColor` | type | `./ui/theme` | — |
|
|
449
|
+
| `RingBuffer` | class | `./core/RingBuffer` | — |
|
|
450
|
+
| `RingBufferOptions` | interface | `./core/RingBuffer` | — |
|
|
451
|
+
| `RingBufferOverflow` | type | `./core/RingBuffer` | — |
|
|
452
|
+
| `SampleCopyLayout` | type | `./core/types` | — |
|
|
453
|
+
| `SeriesConfig` | interface | `./core/types` | — |
|
|
454
|
+
| `SeriesMode` | type | `./core/types` | — |
|
|
455
|
+
| `SeriesSample` | interface | `./core/types` | — |
|
|
456
|
+
| `SeriesStore` | class | `./core/SeriesStore` | — |
|
|
457
|
+
| `SeriesStyle` | interface | `./core/types` | — |
|
|
458
|
+
| `SeriesYAxis` | type | `./core/types` | — |
|
|
459
|
+
| `StaticDataset` | class | `./core/StaticDataset` | — |
|
|
460
|
+
| `StaticOhlcDataset` | class | `./core/OhlcDataset` | — |
|
|
461
|
+
| `TextOverlayConfig` | interface | `./ui/Chart` | — |
|
|
462
|
+
| `ThemeColor` | type | `./ui/theme` | — |
|
|
463
|
+
| `TimeRange` | interface | `./core/types` | — |
|
|
464
|
+
| `TypedSeriesConfig` | type | `./ui/Chart` | — |
|
|
465
|
+
| `UniformRingBuffer` | class | `./core/UniformRingBuffer` | High-throughput ring buffer for uniformly spaced X values. Store only Y samples and derive X as `xStart + index * xStep`. This is the fastest built-in dataset for live telemetry, signals, and other fixed-rate streams because appends copy a single typed array and min/max extraction uses a block segment tree over the physical ring. |
|
|
466
|
+
| `UniformRingBufferOptions` | interface | `./core/UniformRingBuffer` | — |
|
|
467
|
+
| `Viewport` | interface | `./core/types` | — |
|
|
468
|
+
| `ViewportPolicy` | interface | `./interaction/types` | — |
|
|
469
|
+
| `VisiblePointCopyDataset` | interface | `./core/types` | Optional high-performance extraction capability for point/scatter datasets. Implementations should cull against the full 2D viewport and may sample in screen space so dense point clouds respond to both X and Y zoom. |
|
|
470
|
+
| `VisibleSampleCopyDataset` | interface | `./core/types` | Optional high-performance stable visible sampling capability. Unlike copySamplesRange, this method may stride/downsample, but should choose samples anchored to data coordinates so streamed appends do not make existing sampled points jitter. |
|
|
471
|
+
| `YAppendableDataset` | interface | `./core/types` | — |
|
|
472
|
+
| `ZoomAxis` | type | `./interaction/types` | — |
|
|
473
|
+
| `ZoomIntent` | interface | `./interaction/types` | — |
|
|
474
|
+
|
|
475
|
+
</details>
|
|
476
|
+
<!-- README_DOCS_END -->
|
|
238
477
|
|
|
239
478
|
## Architecture
|
|
240
479
|
|
|
@@ -246,12 +485,25 @@ src/
|
|
|
246
485
|
ui/ # Orchestrator (Chart)
|
|
247
486
|
```
|
|
248
487
|
|
|
488
|
+
## Contributing
|
|
489
|
+
|
|
490
|
+
Keep pull requests small and focused. One feature or fix per PR.
|
|
491
|
+
|
|
492
|
+
Branch flow:
|
|
493
|
+
|
|
494
|
+
- `development` is the integration branch for regular work.
|
|
495
|
+
- Open feature/fix PRs into `development`.
|
|
496
|
+
- Open release PRs from `development` into `main` with the version and changelog already updated.
|
|
497
|
+
- Merging an unpublished version to `main` runs CI, publishes npm, creates the `vX.Y.Z` tag, and creates the GitHub Release.
|
|
498
|
+
|
|
249
499
|
## Development
|
|
250
500
|
|
|
251
501
|
```bash
|
|
252
502
|
bun install
|
|
253
|
-
bun run dev
|
|
254
|
-
bun run
|
|
255
|
-
bun
|
|
256
|
-
bun
|
|
503
|
+
bun run dev # Vite dev server → preview/
|
|
504
|
+
bun run ci # Typecheck + tests + package build
|
|
505
|
+
bun run build # Package build (JS + declarations)
|
|
506
|
+
bun test # Tests
|
|
507
|
+
bun run typecheck # TypeScript strict check
|
|
508
|
+
bun run version:patch # Prepare package.json + changelog for a patch release PR
|
|
257
509
|
```
|