blazeplot 0.1.1 → 0.1.2

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 CHANGED
@@ -5,18 +5,9 @@
5
5
  [![license](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6
6
  [![build](https://img.shields.io/github/actions/workflow/status/Federicocervelli/blazeplot/release.yml?branch=master)](https://github.com/Federicocervelli/blazeplot/actions)
7
7
 
8
- Real-time LOD time series rendering engine for the browser.
8
+ Fast WebGL2 plotting engine for the browser 🔥
9
9
 
10
- BlazePlot is GPU-native plotting engineered for high-frequency streaming data where standard charting libraries (Chart.js, ECharts, uPlot) fall over. Instead of drawing every sample, it keeps a resident ring buffer of millions of points, builds a min/max LOD pyramid, and renders only what each pixel needs — so frame cost is `O(pixels)`, not `O(samples)`.
11
-
12
- Built on WebGL2 + [regl](https://github.com/regl-project/regl). No Canvas2D, no SVG, no DOM layout.
13
-
14
- ## Target
15
-
16
- - **10M+** resident points per series
17
- - **60 Hz** smooth append + render
18
- - **Zero allocations** in the frame loop
19
- - **Multi-series** with independent buffers and LOD
10
+ GPU-native, zero DOM. Built on WebGL2 + [regl](https://github.com/regl-project/regl). No Canvas2D, no SVG, no layout thrashing.
20
11
 
21
12
  ## Installation
22
13
 
@@ -44,19 +35,18 @@ const series = chart.addSeries(
44
35
  chart.setViewport({ xMin: 0, xMax: 1000, yMin: -2, yMax: 2 });
45
36
  chart.start();
46
37
 
47
- // Append data periodically
38
+ const xs = new Float64Array(256);
39
+ const ys = new Float32Array(256);
40
+ let t = 0;
41
+
48
42
  function push() {
49
- const n = 256;
50
- const xs = new Float64Array(n);
51
- const ys = new Float32Array(n);
52
- for (let i = 0; i < n; i++) {
43
+ for (let i = 0; i < 256; i++) {
53
44
  xs[i] = t++;
54
45
  ys[i] = Math.sin(t * 0.01) * 0.5 + Math.random() * 0.01;
55
46
  }
56
47
  series.append(xs, ys);
57
48
  requestAnimationFrame(push);
58
49
  }
59
- let t = 0;
60
50
  push();
61
51
  ```
62
52
 
@@ -64,12 +54,13 @@ push();
64
54
 
65
55
  | | |
66
56
  |---|---|
67
- | **LOD downsampling** | Min/max pyramid automatically selects the right detail level for the visible range — sparse viewports show raw points, dense viewports show vertical min/max segments. |
68
- | **Streaming append** | Fixed-capacity ring buffer wraps silently. No re-allocation. No memory growth. |
69
- | **Pan & zoom** | Pointer/touch pan and wheel zoom via `Camera2D`. Customizable viewport policies (e.g. live-follow X while Y is free). |
57
+ | **WebGL2 rendering** | GPU-accelerated from the ground up. No Canvas2D fallback, no DOM text nodes. |
58
+ | **Flexible data model** | Streaming ring buffer or static arrays. Bring your own data shape. |
59
+ | **LOD downsampling** | Min/max pyramid for efficient line rendering at any zoom level sparse views show raw points, dense views show vertical segments. |
60
+ | **Pan & zoom** | Pointer/touch pan and wheel zoom via `Camera2D`. Customizable viewport policies. |
70
61
  | **Grid lines** | Data-anchored grid rendered as WebGL line lists. |
71
62
  | **Multi-series** | Independent buffers, styles, and visibility per series. |
72
- | **No DOM** | No axis DOM elements, no SVG overlay. The canvas owns everything. |
63
+ | **Benchmark overlay** | Built-in fps, frame time, vertex count, draw calls. |
73
64
  | **ResizeObserver** | Automatic DPR-aware canvas sizing. |
74
65
 
75
66
  ## API
@@ -111,8 +102,8 @@ push();
111
102
 
112
103
  | Signature | Description |
113
104
  |---|---|
114
- | `series.append(xs, ys)` | Append typed arrays of X (Float64) and Y (Float32) values. |
115
- | `series.clear()` | Clear all data and reset LOD state. |
105
+ | `series.append(xs, ys)` | Append typed arrays of X and Y values (streaming). |
106
+ | `series.clear()` | Clear all data and reset. |
116
107
  | `series.setVisible(v)` | Toggle visibility. |
117
108
  | `series.visible` | Current visibility state. |
118
109
  | `series.length` | Number of samples buffered. |
@@ -123,7 +114,7 @@ push();
123
114
  |---|---|
124
115
  | `mode` | `"line"` / `"envelope"` / `"scatter"` (envelope and scatter roadmap-only). |
125
116
  | `capacity` | Ring buffer capacity (samples). |
126
- | `downsample` | `"minmax"` (the only LOD strategy). |
117
+ | `downsample` | `"minmax"` (LOD for line rendering). |
127
118
 
128
119
  ### `SeriesStyle`
129
120
 
@@ -142,36 +133,15 @@ interface ViewportPolicy {
142
133
  }
143
134
  ```
144
135
 
145
- Built-in data types: `Viewport`, `PanIntent`, `ZoomIntent`, `ZoomAxis`.
146
-
147
136
  ### Lower-level primitives
148
137
 
149
- `Camera2D`, `RingBuffer`, `MinMaxPyramid`, `AxisController` are exported for advanced use cases (custom pipelines, worker threads, offscreen rendering).
150
-
151
- ## How it works
152
-
153
- ```
154
- Data stream ──► RingBuffer (resident, wraps at capacity)
155
-
156
-
157
- MinMaxPyramid (full rebuild today, incremental roadmap)
158
-
159
-
160
- SeriesStore.query() ──► LODView (buckets for visible range)
161
-
162
-
163
- Renderer (regl / WebGL2)
164
- ```
165
-
166
- The render loop decides per-frame:
167
- - **Few visible samples** → raw line strip from ring buffer
168
- - **Many visible samples** → min/max vertical segments from the pyramid
138
+ `Camera2D`, `RingBuffer`, `MinMaxPyramid`, `AxisController` are exported for advanced use cases.
169
139
 
170
140
  ## Architecture
171
141
 
172
142
  ```
173
143
  src/
174
- core/ # Data engineno UI, no GPU
144
+ core/ # Data modelseries, datasets, LOD
175
145
  render/ # GPU abstraction + regl backend
176
146
  interaction/ # Camera, input, axis ticks
177
147
  ui/ # Orchestrator (Chart)
@@ -184,7 +154,7 @@ bun install
184
154
  bun run dev # Vite dev server → preview/
185
155
  bun run build # Package build (JS + declarations)
186
156
  bun run build:js # JS-only build
187
- bun test # Core data-structure tests
157
+ bun test # Tests
188
158
  bun run typecheck # TypeScript strict check
189
159
  ```
190
160
 
@@ -199,8 +169,8 @@ Output:
199
169
  ```
200
170
  dist/index.js ES module
201
171
  dist/index.d.ts TypeScript declarations
202
- dist/index.js.map Source map
203
- dist/*.d.ts.map Declaration maps
204
172
  ```
205
173
 
174
+ ## Why WebGL2?
206
175
 
176
+ Canvas2D and SVG are CPU-bound — every point becomes a draw call or a DOM node. BlazePlot keeps data on the GPU, streams only visible vertices, and avoids DOM entirely. For dense line plots (millions of points), interactive scatter, or real-time streaming, the difference is orders of magnitude.
@@ -1,8 +1,8 @@
1
- import { RingBuffer } from './RingBuffer.js';
1
+ import { Dataset } from './types.js';
2
2
  export declare class DataCursor {
3
3
  private _index;
4
4
  private _buffer;
5
- bind(buffer: RingBuffer): void;
5
+ bind(buffer: Dataset): void;
6
6
  get index(): number;
7
7
  seekTimestamp(x: number): number;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DataCursor.d.ts","sourceRoot":"","sources":["../../src/core/DataCursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAA2B;IAE1C,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAK9B,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;CAYjC"}
1
+ {"version":3,"file":"DataCursor.d.ts","sourceRoot":"","sources":["../../src/core/DataCursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAwB;IAEvC,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAK3B,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;CAYjC"}
@@ -1,12 +1,11 @@
1
- import { LODView, Viewport } from './types.js';
2
- import { RingBuffer } from './RingBuffer.js';
1
+ import { Dataset, LODView, Viewport } from './types.js';
3
2
  export declare class MinMaxPyramid {
4
3
  readonly bucketSize: number;
5
4
  private levels;
6
5
  private levelLengths;
7
6
  private levelSampleWidths;
8
7
  constructor(bucketSize?: number);
9
- build(source: RingBuffer): void;
8
+ build(source: Dataset): void;
10
9
  query(_viewport: Viewport, pixelWidth: number, xRange: {
11
10
  start: number;
12
11
  length: number;
@@ -1 +1 @@
1
- {"version":3,"file":"MinMaxPyramid.d.ts","sourceRoot":"","sources":["../../src/core/MinMaxPyramid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C,qBAAa,aAAa;IAKZ,QAAQ,CAAC,UAAU,EAAE,MAAM;IAJvC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,iBAAiB,CAAc;gBAElB,UAAU,GAAE,MAAU;IAS3C,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAgD/B,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;CAsCnG"}
1
+ {"version":3,"file":"MinMaxPyramid.d.ts","sourceRoot":"","sources":["../../src/core/MinMaxPyramid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI7D,qBAAa,aAAa;IAKZ,QAAQ,CAAC,UAAU,EAAE,MAAM;IAJvC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,iBAAiB,CAAc;gBAElB,UAAU,GAAE,MAAU;IAS3C,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAgD5B,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;CAsCnG"}
@@ -9,6 +9,7 @@ export declare class RingBuffer {
9
9
  get length(): number;
10
10
  get range(): TimeRange | null;
11
11
  push(x: number, y: number): void;
12
+ append(x: ArrayLike<number>, y: ArrayLike<number>): void;
12
13
  get(index: number): {
13
14
  x: number;
14
15
  y: number;
@@ -1 +1 @@
1
- {"version":3,"file":"RingBuffer.d.ts","sourceRoot":"","sources":["../../src/core/RingBuffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,qBAAa,UAAU;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,KAAK,CAAa;IAE1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,QAAQ,EAAE,MAAM;IAU5B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,KAAK,IAAI,SAAS,GAAG,IAAI,CAG5B;IAED,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAOhC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKnD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAK3B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAK3B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAW9B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAW9B,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,gBAAgB;CAKzB"}
1
+ {"version":3,"file":"RingBuffer.d.ts","sourceRoot":"","sources":["../../src/core/RingBuffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,qBAAa,UAAU;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,KAAK,CAAa;IAE1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,QAAQ,EAAE,MAAM;IAU5B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,KAAK,IAAI,SAAS,GAAG,IAAI,CAG5B;IAED,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAOhC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI;IAOxD,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKnD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAK3B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAK3B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAW9B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAW9B,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,gBAAgB;CAKzB"}
@@ -1,12 +1,12 @@
1
- import { SeriesConfig, SeriesStyle, LODView, Viewport } from './types.js';
1
+ import { Dataset, LODView, Viewport, SeriesConfig, SeriesStyle } from './types.js';
2
2
  export declare class SeriesStore {
3
3
  readonly config: SeriesConfig;
4
4
  readonly style: SeriesStyle;
5
- private readonly buffer;
5
+ private readonly dataset;
6
6
  private readonly pyramid;
7
7
  private _dirty;
8
8
  private _visible;
9
- constructor(config: SeriesConfig, style: SeriesStyle);
9
+ constructor(dataset: Dataset, config: SeriesConfig, style: SeriesStyle);
10
10
  get dirty(): boolean;
11
11
  get length(): number;
12
12
  get visible(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"SeriesStore.d.ts","sourceRoot":"","sources":["../../src/core/SeriesStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI/E,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IAExC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAiB;gBAErB,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW;IAOpD,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIlC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI;IAQxD,KAAK,IAAI,IAAI;IAMb,cAAc,IAAI,IAAI;IAMtB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAetD,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM;IAM9C,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAmBnF,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM;CAqCzF"}
1
+ {"version":3,"file":"SeriesStore.d.ts","sourceRoot":"","sources":["../../src/core/SeriesStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG3G,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IAExC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAiB;gBAErB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW;IAWtE,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIlC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI;IAUxD,KAAK,IAAI,IAAI;IAUb,cAAc,IAAI,IAAI;IAMtB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAetD,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM;IAM9C,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAmBnF,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM;CAqCzF"}
@@ -0,0 +1,14 @@
1
+ import { Dataset, TimeRange } from './types.js';
2
+ export declare class StaticDataset implements Dataset {
3
+ private readonly xData;
4
+ private readonly yData;
5
+ constructor(xData: ArrayLike<number>, yData: ArrayLike<number>);
6
+ get length(): number;
7
+ get range(): TimeRange | null;
8
+ getX(index: number): number;
9
+ getY(index: number): number;
10
+ lowerBoundX(x: number): number;
11
+ upperBoundX(x: number): number;
12
+ private assertValidIndex;
13
+ }
14
+ //# sourceMappingURL=StaticDataset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StaticDataset.d.ts","sourceRoot":"","sources":["../../src/core/StaticDataset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAErD,qBAAa,aAAc,YAAW,OAAO;IAEzC,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,EACxB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC;IAG3C,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,KAAK,IAAI,SAAS,GAAG,IAAI,CAG5B;IAED,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAK3B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAK3B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAW9B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAW9B,OAAO,CAAC,gBAAgB;CAKzB"}
@@ -1,5 +1,6 @@
1
- export type { Viewport, LODBucket, LODView, TimeRange, SeriesStyle, SeriesMode, SeriesConfig } from './types.js';
1
+ export type { Viewport, LODBucket, LODView, TimeRange, SeriesStyle, SeriesMode, SeriesConfig, Dataset, AppendableDataset } from './types.js';
2
2
  export { RingBuffer } from './RingBuffer.js';
3
+ export { StaticDataset } from './StaticDataset.js';
3
4
  export { MinMaxPyramid } from './MinMaxPyramid.js';
4
5
  export { SeriesStore } from './SeriesStore.js';
5
6
  export { DataCursor } from './DataCursor.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE7I,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -25,9 +25,23 @@ export interface SeriesStyle {
25
25
  readonly lineWidth: number;
26
26
  }
27
27
  export type SeriesMode = "line" | "envelope" | "scatter";
28
+ export interface Dataset {
29
+ readonly length: number;
30
+ readonly range: TimeRange | null;
31
+ getX(index: number): number;
32
+ getY(index: number): number;
33
+ lowerBoundX(x: number): number;
34
+ upperBoundX(x: number): number;
35
+ }
36
+ export interface AppendableDataset extends Dataset {
37
+ push(x: number, y: number): void;
38
+ append(x: ArrayLike<number>, y: ArrayLike<number>): void;
39
+ clear(): void;
40
+ }
28
41
  export interface SeriesConfig {
29
42
  readonly mode: SeriesMode;
30
43
  readonly capacity: number;
31
44
  readonly downsample: "minmax";
45
+ readonly dataset?: Dataset;
32
46
  }
33
47
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;CAC/B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,iBAAkB,SAAQ,OAAO;IAChD,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B"}
package/dist/index.d.ts CHANGED
@@ -2,9 +2,10 @@ export { Chart } from './ui/Chart.js';
2
2
  export type { ChartFrameStats, ChartOptions } from './ui/Chart.js';
3
3
  export { SeriesStore } from './core/SeriesStore.js';
4
4
  export { RingBuffer } from './core/RingBuffer.js';
5
+ export { StaticDataset } from './core/StaticDataset.js';
5
6
  export { MinMaxPyramid } from './core/MinMaxPyramid.js';
6
7
  export { Camera2D } from './interaction/Camera2D.js';
7
8
  export { AxisController } from './interaction/AxisController.js';
8
- export type { Viewport, LODBucket, LODView, TimeRange, SeriesStyle, SeriesMode, SeriesConfig } from './core/types.js';
9
+ export type { Viewport, LODBucket, LODView, TimeRange, SeriesStyle, SeriesMode, SeriesConfig, Dataset, AppendableDataset } from './core/types.js';
9
10
  export type { PanIntent, ZoomAxis, ZoomIntent, ViewportPolicy } from './interaction/types.js';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtH,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAClJ,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -1,94 +1,35 @@
1
1
  import e from "regl";
2
- //#region src/core/RingBuffer.ts
3
- var t = class {
4
- capacity;
5
- _length = 0;
6
- _head = 0;
7
- xData;
8
- yData;
9
- constructor(e) {
10
- if (!Number.isInteger(e) || e <= 0) throw RangeError("RingBuffer capacity must be a positive integer.");
11
- this.capacity = e, this.xData = new Float64Array(e), this.yData = new Float32Array(e);
12
- }
13
- get length() {
14
- return this._length;
15
- }
16
- get range() {
17
- return this._length === 0 ? null : {
18
- start: this.getX(0),
19
- end: this.getX(this._length - 1)
20
- };
21
- }
22
- push(e, t) {
23
- this.xData[this._head] = e, this.yData[this._head] = t, this._head = (this._head + 1) % this.capacity, this._length < this.capacity && this._length++;
24
- }
25
- get(e) {
26
- return e < 0 || e >= this._length ? null : {
27
- x: this.getX(e),
28
- y: this.getY(e)
29
- };
30
- }
31
- getX(e) {
32
- return this.assertValidIndex(e), this.xData[this.logicalToPhysical(e)];
33
- }
34
- getY(e) {
35
- return this.assertValidIndex(e), this.yData[this.logicalToPhysical(e)];
36
- }
37
- lowerBoundX(e) {
38
- let t = 0, n = this._length;
39
- for (; t < n;) {
40
- let r = t + (n - t >> 1);
41
- this.getX(r) < e ? t = r + 1 : n = r;
42
- }
43
- return t;
44
- }
45
- upperBoundX(e) {
46
- let t = 0, n = this._length;
47
- for (; t < n;) {
48
- let r = t + (n - t >> 1);
49
- this.getX(r) <= e ? t = r + 1 : n = r;
50
- }
51
- return t;
52
- }
53
- clear() {
54
- this._length = 0, this._head = 0;
55
- }
56
- logicalToPhysical(e) {
57
- return (this._head - this._length + e + this.capacity) % this.capacity;
58
- }
59
- assertValidIndex(e) {
60
- if (!Number.isInteger(e) || e < 0 || e >= this._length) throw RangeError(`RingBuffer index out of range: ${e}`);
61
- }
62
- }, n = 16, r = class {
2
+ //#region src/core/MinMaxPyramid.ts
3
+ var t = 16, n = class {
63
4
  bucketSize;
64
5
  levels = [];
65
6
  levelLengths;
66
7
  levelSampleWidths;
67
8
  constructor(e = 2) {
68
9
  if (this.bucketSize = e, !Number.isInteger(e) || e < 2) throw RangeError("MinMaxPyramid bucketSize must be an integer >= 2.");
69
- this.levelLengths = new Uint32Array(n), this.levelSampleWidths = new Uint32Array(n);
10
+ this.levelLengths = new Uint32Array(t), this.levelSampleWidths = new Uint32Array(t);
70
11
  }
71
12
  build(e) {
72
13
  this.levels = [], this.levelLengths.fill(0), this.levelSampleWidths.fill(0);
73
- let t = e.length;
74
- if (t === 0) return;
14
+ let n = e.length;
15
+ if (n === 0) return;
75
16
  let r = null, i = 0;
76
- for (; t > 0 && i < n;) {
77
- let n = Math.ceil(t / this.bucketSize), a = new Float32Array(n * 2);
78
- for (let n = 0; n < t; n += this.bucketSize) {
79
- let i = Infinity, o = -Infinity, s = Math.min(n + this.bucketSize, t);
80
- for (let t = n; t < s; t++) if (r) {
81
- let e = r[t * 2], n = r[t * 2 + 1];
82
- e < i && (i = e), n > o && (o = n);
17
+ for (; n > 0 && i < t;) {
18
+ let t = Math.ceil(n / this.bucketSize), a = new Float32Array(t * 2);
19
+ for (let t = 0; t < n; t += this.bucketSize) {
20
+ let i = Infinity, o = -Infinity, s = Math.min(t + this.bucketSize, n);
21
+ for (let n = t; n < s; n++) if (r) {
22
+ let e = r[n * 2], t = r[n * 2 + 1];
23
+ e < i && (i = e), t > o && (o = t);
83
24
  } else {
84
- let n = e.getY(t);
85
- n < i && (i = n), n > o && (o = n);
25
+ let t = e.getY(n);
26
+ t < i && (i = t), t > o && (o = t);
86
27
  }
87
- let c = Math.floor(n / this.bucketSize);
28
+ let c = Math.floor(t / this.bucketSize);
88
29
  a[c * 2] = i, a[c * 2 + 1] = o;
89
30
  }
90
- if (this.levels[i] = a, this.levelLengths[i] = n, this.levelSampleWidths[i] = this.bucketSize ** (i + 1), n === 1) break;
91
- r = a, t = n, i++;
31
+ if (this.levels[i] = a, this.levelLengths[i] = t, this.levelSampleWidths[i] = this.bucketSize ** (i + 1), t === 1) break;
32
+ r = a, n = t, i++;
92
33
  }
93
34
  }
94
35
  query(e, t, n) {
@@ -124,21 +65,21 @@ var t = class {
124
65
  samplesPerPixel: i
125
66
  };
126
67
  }
127
- }, i = class {
68
+ }, r = class {
128
69
  config;
129
70
  style;
130
- buffer;
71
+ dataset;
131
72
  pyramid;
132
73
  _dirty = !1;
133
74
  _visible = !0;
134
- constructor(e, n) {
135
- this.config = e, this.buffer = new t(e.capacity), this.pyramid = new r(), this.style = n;
75
+ constructor(e, t, r) {
76
+ this.dataset = e, this.config = t, this.pyramid = new n(), this.style = r, e.length > 0 && this.pyramid.build(e);
136
77
  }
137
78
  get dirty() {
138
79
  return this._dirty;
139
80
  }
140
81
  get length() {
141
- return this.buffer.length;
82
+ return this.dataset.length;
142
83
  }
143
84
  get visible() {
144
85
  return this._visible;
@@ -147,57 +88,120 @@ var t = class {
147
88
  this._visible = e;
148
89
  }
149
90
  append(e, t) {
150
- let n = Math.min(e.length, t.length);
151
- for (let r = 0; r < n; r++) this.buffer.push(e[r], t[r]);
152
- this._dirty = !0;
91
+ if (!("push" in this.dataset)) throw TypeError("SeriesStore dataset is not appendable.");
92
+ this.dataset.append(e, t), this._dirty = !0;
153
93
  }
154
94
  clear() {
155
- this.buffer.clear(), this.pyramid.build(this.buffer), this._dirty = !1;
95
+ if (!("clear" in this.dataset)) throw TypeError("SeriesStore dataset is not clearable.");
96
+ this.dataset.clear(), this.pyramid.build(this.dataset), this._dirty = !1;
156
97
  }
157
98
  rebuildPyramid() {
158
- this._dirty &&= (this.pyramid.build(this.buffer), !1);
99
+ this._dirty &&= (this.pyramid.build(this.dataset), !1);
159
100
  }
160
101
  query(e, t) {
161
- if (!this.buffer.range) return {
102
+ if (!this.dataset.range) return {
162
103
  buckets: new Float32Array(),
163
104
  bucketCount: 0,
164
105
  level: 0,
165
106
  samplesPerPixel: 0
166
107
  };
167
- let n = this.buffer.lowerBoundX(e.xMin), r = this.buffer.upperBoundX(e.xMax);
108
+ let n = this.dataset.lowerBoundX(e.xMin), r = this.dataset.upperBoundX(e.xMax);
168
109
  return this.pyramid.query(e, t, {
169
110
  start: n,
170
111
  length: Math.max(0, r - n)
171
112
  });
172
113
  }
173
114
  visibleSampleCount(e) {
174
- let t = this.buffer.lowerBoundX(e.xMin), n = this.buffer.upperBoundX(e.xMax);
115
+ let t = this.dataset.lowerBoundX(e.xMin), n = this.dataset.upperBoundX(e.xMax);
175
116
  return Math.max(0, n - t);
176
117
  }
177
118
  copyRawVisible(e, t, n) {
178
119
  if (n <= 0 || t.length < n * 2) return 0;
179
- let r = this.buffer.lowerBoundX(e.xMin), i = this.buffer.upperBoundX(e.xMax), a = i - r;
120
+ let r = this.dataset.lowerBoundX(e.xMin), i = this.dataset.upperBoundX(e.xMax), a = i - r;
180
121
  if (a <= 0) return 0;
181
122
  let o = Math.max(1, Math.ceil(a / n)), s = 0;
182
- for (let e = r; e < i && s < n; e += o) t[s * 2] = this.buffer.getX(e), t[s * 2 + 1] = this.buffer.getY(e), s++;
123
+ for (let e = r; e < i && s < n; e += o) t[s * 2] = this.dataset.getX(e), t[s * 2 + 1] = this.dataset.getY(e), s++;
183
124
  return s;
184
125
  }
185
126
  copyMinMaxVisible(e, t, n) {
186
127
  if (n <= 0 || t.length < n * 4) return 0;
187
- let r = this.buffer.lowerBoundX(e.xMin), i = this.buffer.upperBoundX(e.xMax), a = i - r;
128
+ let r = this.dataset.lowerBoundX(e.xMin), i = this.dataset.upperBoundX(e.xMax), a = i - r;
188
129
  if (a <= 0) return 0;
189
130
  let o = Math.min(n, a), s = 0;
190
131
  for (let e = 0; e < o; e++) {
191
132
  let n = r + Math.floor(e * a / o), c = r + Math.max(Math.floor((e + 1) * a / o), Math.floor(e * a / o) + 1), l = Math.min(i, c), u = Infinity, d = -Infinity;
192
133
  for (let e = n; e < l; e++) {
193
- let t = this.buffer.getY(e);
134
+ let t = this.dataset.getY(e);
194
135
  t < u && (u = t), t > d && (d = t);
195
136
  }
196
- let f = this.buffer.getX(n + (l - n >> 1));
137
+ let f = this.dataset.getX(n + (l - n >> 1));
197
138
  t[s * 2] = f, t[s * 2 + 1] = u, s++, t[s * 2] = f, t[s * 2 + 1] = d, s++;
198
139
  }
199
140
  return s;
200
141
  }
142
+ }, i = class {
143
+ capacity;
144
+ _length = 0;
145
+ _head = 0;
146
+ xData;
147
+ yData;
148
+ constructor(e) {
149
+ if (!Number.isInteger(e) || e <= 0) throw RangeError("RingBuffer capacity must be a positive integer.");
150
+ this.capacity = e, this.xData = new Float64Array(e), this.yData = new Float32Array(e);
151
+ }
152
+ get length() {
153
+ return this._length;
154
+ }
155
+ get range() {
156
+ return this._length === 0 ? null : {
157
+ start: this.getX(0),
158
+ end: this.getX(this._length - 1)
159
+ };
160
+ }
161
+ push(e, t) {
162
+ this.xData[this._head] = e, this.yData[this._head] = t, this._head = (this._head + 1) % this.capacity, this._length < this.capacity && this._length++;
163
+ }
164
+ append(e, t) {
165
+ let n = Math.min(e.length, t.length);
166
+ for (let r = 0; r < n; r++) this.push(e[r], t[r]);
167
+ }
168
+ get(e) {
169
+ return e < 0 || e >= this._length ? null : {
170
+ x: this.getX(e),
171
+ y: this.getY(e)
172
+ };
173
+ }
174
+ getX(e) {
175
+ return this.assertValidIndex(e), this.xData[this.logicalToPhysical(e)];
176
+ }
177
+ getY(e) {
178
+ return this.assertValidIndex(e), this.yData[this.logicalToPhysical(e)];
179
+ }
180
+ lowerBoundX(e) {
181
+ let t = 0, n = this._length;
182
+ for (; t < n;) {
183
+ let r = t + (n - t >> 1);
184
+ this.getX(r) < e ? t = r + 1 : n = r;
185
+ }
186
+ return t;
187
+ }
188
+ upperBoundX(e) {
189
+ let t = 0, n = this._length;
190
+ for (; t < n;) {
191
+ let r = t + (n - t >> 1);
192
+ this.getX(r) <= e ? t = r + 1 : n = r;
193
+ }
194
+ return t;
195
+ }
196
+ clear() {
197
+ this._length = 0, this._head = 0;
198
+ }
199
+ logicalToPhysical(e) {
200
+ return (this._head - this._length + e + this.capacity) % this.capacity;
201
+ }
202
+ assertValidIndex(e) {
203
+ if (!Number.isInteger(e) || e < 0 || e >= this._length) throw RangeError(`RingBuffer index out of range: ${e}`);
204
+ }
201
205
  }, a = {
202
206
  line: {
203
207
  vert: "attribute vec2 position;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n",
@@ -583,7 +587,7 @@ var c = class {
583
587
  }, typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.resize()), this.resizeObserver.observe(this.canvas));
584
588
  }
585
589
  addSeries(e, t) {
586
- let n = new i(e, {
590
+ let n = new r(e.dataset ?? new i(e.capacity), e, {
587
591
  color: t?.color ?? [
588
592
  .3,
589
593
  .6,
@@ -662,8 +666,48 @@ var c = class {
662
666
  recordRenderMode(e) {
663
667
  this.stats.renderMode === "none" ? this.stats.renderMode = e : this.stats.renderMode !== e && (this.stats.renderMode = "mixed");
664
668
  }
669
+ }, h = class {
670
+ xData;
671
+ yData;
672
+ constructor(e, t) {
673
+ this.xData = e, this.yData = t;
674
+ }
675
+ get length() {
676
+ return Math.min(this.xData.length, this.yData.length);
677
+ }
678
+ get range() {
679
+ return this.length === 0 ? null : {
680
+ start: this.xData[0],
681
+ end: this.xData[this.length - 1]
682
+ };
683
+ }
684
+ getX(e) {
685
+ return this.assertValidIndex(e), this.xData[e];
686
+ }
687
+ getY(e) {
688
+ return this.assertValidIndex(e), this.yData[e];
689
+ }
690
+ lowerBoundX(e) {
691
+ let t = 0, n = this.length;
692
+ for (; t < n;) {
693
+ let r = t + (n - t >> 1);
694
+ this.xData[r] < e ? t = r + 1 : n = r;
695
+ }
696
+ return t;
697
+ }
698
+ upperBoundX(e) {
699
+ let t = 0, n = this.length;
700
+ for (; t < n;) {
701
+ let r = t + (n - t >> 1);
702
+ this.xData[r] <= e ? t = r + 1 : n = r;
703
+ }
704
+ return t;
705
+ }
706
+ assertValidIndex(e) {
707
+ if (!Number.isInteger(e) || e < 0 || e >= this.length) throw RangeError(`StaticDataset index out of range: ${e}`);
708
+ }
665
709
  };
666
710
  //#endregion
667
- export { d as AxisController, u as Camera2D, m as Chart, r as MinMaxPyramid, t as RingBuffer, i as SeriesStore };
711
+ export { d as AxisController, u as Camera2D, m as Chart, n as MinMaxPyramid, i as RingBuffer, r as SeriesStore, h as StaticDataset };
668
712
 
669
713
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/core/RingBuffer.ts","../src/core/MinMaxPyramid.ts","../src/core/SeriesStore.ts","../src/render/ShaderPrograms.ts","../src/render/Renderer.ts","../src/render/ReglBackend.ts","../src/interaction/InputController.ts","../src/interaction/Camera2D.ts","../src/interaction/AxisController.ts","../src/ui/Chart.ts"],"sourcesContent":["import type { TimeRange } from \"./types.js\";\n\nexport class RingBuffer {\n readonly capacity: number;\n private _length: number = 0;\n private _head: number = 0;\n\n private readonly xData: Float64Array;\n private readonly yData: Float32Array;\n\n constructor(capacity: number) {\n if (!Number.isInteger(capacity) || capacity <= 0) {\n throw new RangeError(\"RingBuffer capacity must be a positive integer.\");\n }\n\n this.capacity = capacity;\n this.xData = new Float64Array(capacity);\n this.yData = new Float32Array(capacity);\n }\n\n get length(): number {\n return this._length;\n }\n\n get range(): TimeRange | null {\n if (this._length === 0) return null;\n return { start: this.getX(0), end: this.getX(this._length - 1) };\n }\n\n push(x: number, y: number): void {\n this.xData[this._head] = x;\n this.yData[this._head] = y;\n this._head = (this._head + 1) % this.capacity;\n if (this._length < this.capacity) this._length++;\n }\n\n get(index: number): { x: number; y: number } | null {\n if (index < 0 || index >= this._length) return null;\n return { x: this.getX(index), y: this.getY(index) };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[this.logicalToPhysical(index)]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[this.logicalToPhysical(index)]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n clear(): void {\n this._length = 0;\n this._head = 0;\n }\n\n private logicalToPhysical(index: number): number {\n return (this._head - this._length + index + this.capacity) % this.capacity;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this._length) {\n throw new RangeError(`RingBuffer index out of range: ${index}`);\n }\n }\n}\n","import type { LODView, Viewport } from \"./types.js\";\nimport { RingBuffer } from \"./RingBuffer.js\";\n\nconst MAX_LEVELS = 16;\n\nexport class MinMaxPyramid {\n private levels: Float32Array[] = [];\n private levelLengths: Uint32Array;\n private levelSampleWidths: Uint32Array;\n\n constructor(readonly bucketSize: number = 2) {\n if (!Number.isInteger(bucketSize) || bucketSize < 2) {\n throw new RangeError(\"MinMaxPyramid bucketSize must be an integer >= 2.\");\n }\n\n this.levelLengths = new Uint32Array(MAX_LEVELS);\n this.levelSampleWidths = new Uint32Array(MAX_LEVELS);\n }\n\n build(source: RingBuffer): void {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n\n let srcLen = source.length;\n if (srcLen === 0) return;\n\n let prevLevel: Float32Array | null = null;\n let level = 0;\n\n while (srcLen > 0 && level < MAX_LEVELS) {\n const nextLen = Math.ceil(srcLen / this.bucketSize);\n const levelData = new Float32Array(nextLen * 2);\n\n for (let i = 0; i < srcLen; i += this.bucketSize) {\n let minY = Infinity;\n let maxY = -Infinity;\n const end = Math.min(i + this.bucketSize, srcLen);\n for (let j = i; j < end; j++) {\n if (prevLevel) {\n const prevMin = prevLevel[j * 2]!;\n const prevMax = prevLevel[j * 2 + 1]!;\n if (prevMin < minY) minY = prevMin;\n if (prevMax > maxY) maxY = prevMax;\n } else {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n const outIdx = Math.floor(i / this.bucketSize);\n levelData[outIdx * 2] = minY;\n levelData[outIdx * 2 + 1] = maxY;\n }\n\n this.levels[level] = levelData;\n this.levelLengths[level] = nextLen;\n this.levelSampleWidths[level] = this.bucketSize ** (level + 1);\n\n if (nextLen === 1) break;\n\n prevLevel = levelData;\n srcLen = nextLen;\n level++;\n }\n }\n\n query(_viewport: Viewport, pixelWidth: number, xRange: { start: number; length: number }): LODView {\n if (pixelWidth <= 0 || xRange.length <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const visibleSamples = xRange.length;\n const samplesPerPixel = Math.max(1, visibleSamples / pixelWidth);\n const level = Math.min(\n Math.max(0, Math.ceil(Math.log2(samplesPerPixel)) - 1),\n this.levels.length - 1,\n );\n\n const levelData = this.levels[level];\n const levelLen = this.levelLengths[level];\n const sampleWidth = this.levelSampleWidths[level];\n if (!levelData || levelLen === undefined || sampleWidth === undefined || levelLen === 0 || sampleWidth === 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel };\n }\n\n const queryStart = Math.max(0, xRange.start);\n const queryEnd = queryStart + xRange.length;\n const bucketStart = Math.max(0, Math.floor(queryStart / sampleWidth));\n const bucketEnd = Math.min(levelLen, Math.ceil(queryEnd / sampleWidth));\n const count = bucketEnd - bucketStart;\n\n if (count <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level, samplesPerPixel };\n }\n\n const result = new Float32Array(count * 2);\n for (let i = 0; i < count; i++) {\n const j = (bucketStart + i) * 2;\n result[i * 2] = levelData[j]!;\n result[i * 2 + 1] = levelData[j + 1]!;\n }\n\n return { buckets: result, bucketCount: count, level, samplesPerPixel };\n }\n}\n","import type { SeriesConfig, SeriesStyle, LODView, Viewport } from \"./types.js\";\nimport { RingBuffer } from \"./RingBuffer.js\";\nimport { MinMaxPyramid } from \"./MinMaxPyramid.js\";\n\nexport class SeriesStore {\n readonly config: SeriesConfig;\n readonly style: SeriesStyle;\n private readonly buffer: RingBuffer;\n private readonly pyramid: MinMaxPyramid;\n\n private _dirty: boolean = false;\n private _visible: boolean = true;\n\n constructor(config: SeriesConfig, style: SeriesStyle) {\n this.config = config;\n this.buffer = new RingBuffer(config.capacity);\n this.pyramid = new MinMaxPyramid();\n this.style = style;\n }\n\n get dirty(): boolean {\n return this._dirty;\n }\n\n get length(): number {\n return this.buffer.length;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n setVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n const n = Math.min(x.length, y.length);\n for (let i = 0; i < n; i++) {\n this.buffer.push(x[i]!, y[i]!);\n }\n this._dirty = true;\n }\n\n clear(): void {\n this.buffer.clear();\n this.pyramid.build(this.buffer);\n this._dirty = false;\n }\n\n rebuildPyramid(): void {\n if (!this._dirty) return;\n this.pyramid.build(this.buffer);\n this._dirty = false;\n }\n\n query(viewport: Viewport, pixelWidth: number): LODView {\n const range = this.buffer.range;\n if (!range) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n\n return this.pyramid.query(viewport, pixelWidth, {\n start,\n length: Math.max(0, end - start),\n });\n }\n\n visibleSampleCount(viewport: Viewport): number {\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n return Math.max(0, end - start);\n }\n\n copyRawVisible(viewport: Viewport, target: Float32Array, maxPoints: number): number {\n if (maxPoints <= 0 || target.length < maxPoints * 2) return 0;\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const stride = Math.max(1, Math.ceil(visible / maxPoints));\n let count = 0;\n for (let i = start; i < end && count < maxPoints; i += stride) {\n target[count * 2] = this.buffer.getX(i);\n target[count * 2 + 1] = this.buffer.getY(i);\n count++;\n }\n\n return count;\n }\n\n copyMinMaxVisible(viewport: Viewport, target: Float32Array, maxSegments: number): number {\n if (maxSegments <= 0 || target.length < maxSegments * 4) return 0;\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const segmentCount = Math.min(maxSegments, visible);\n let vertexCount = 0;\n for (let segment = 0; segment < segmentCount; segment++) {\n const segmentStart = start + Math.floor((segment * visible) / segmentCount);\n const segmentEnd = start + Math.max(\n Math.floor(((segment + 1) * visible) / segmentCount),\n Math.floor((segment * visible) / segmentCount) + 1,\n );\n const clampedEnd = Math.min(end, segmentEnd);\n\n let minY = Infinity;\n let maxY = -Infinity;\n for (let i = segmentStart; i < clampedEnd; i++) {\n const y = this.buffer.getY(i);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n const x = this.buffer.getX(segmentStart + ((clampedEnd - segmentStart) >> 1));\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = minY;\n vertexCount++;\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = maxY;\n vertexCount++;\n }\n\n return vertexCount;\n }\n}\n","import lineVert from \"./shaders/line.vert?raw\";\nimport lineFrag from \"./shaders/line.frag?raw\";\nimport segmentVert from \"./shaders/segment.vert?raw\";\nimport segmentFrag from \"./shaders/segment.frag?raw\";\n\nexport const ShaderPrograms = {\n line: { vert: lineVert, frag: lineFrag },\n segment: { vert: segmentVert, frag: segmentFrag },\n} as const;\n","import { ShaderPrograms } from \"./ShaderPrograms.js\";\nimport type { Camera2D } from \"../interaction/Camera2D.js\";\nimport type { GpuBackend, GpuBuffer, GpuProgram } from \"./types.js\";\nimport type { SeriesStyle } from \"../core/types.js\";\n\nexport class Renderer {\n private readonly lineProgram: GpuProgram;\n private readonly scaleUniform: Float32Array = new Float32Array(2);\n private readonly offsetUniform: Float32Array = new Float32Array(2);\n\n constructor(private backend: GpuBackend) {\n this.lineProgram = this.backend.createProgram(ShaderPrograms.line.vert, ShaderPrograms.line.frag);\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.backend.clear(r, g, b, a);\n }\n\n createFloatBuffer(floatCount: number): GpuBuffer {\n return this.backend.createBuffer({ usage: \"stream\", type: \"float\", length: floatCount });\n }\n\n updateFloatBuffer(buffer: GpuBuffer, data: Float32Array): void {\n this.backend.updateBuffer(buffer, data);\n }\n\n viewport(x: number, y: number, width: number, height: number): void {\n this.backend.viewport(x, y, width, height);\n }\n\n drawLines(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"lines\", positions, count, style, camera);\n }\n\n drawLineStrip(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"line_strip\", positions, count, style, camera);\n }\n\n private drawLinePrimitive(primitive: \"lines\" | \"line_strip\", positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.scaleUniform[0] = camera.xScale;\n this.scaleUniform[1] = camera.yScale;\n this.offsetUniform[0] = camera.xOffset;\n this.offsetUniform[1] = camera.yOffset;\n\n this.backend.draw({\n program: this.lineProgram,\n primitive,\n count,\n attributes: { position: positions },\n uniforms: {\n uScale: this.scaleUniform,\n uOffset: this.offsetUniform,\n uColor: style.color,\n },\n });\n }\n\n drawMinMaxSegments(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLines(positions, count, style, camera);\n }\n\n dispose(): void {\n this.backend.destroy();\n }\n}\n","import createRegl from \"regl\";\nimport type { AttributeState, Buffer as ReglBuffer, DrawCommand, PrimitiveType, Regl, Uniform } from \"regl\";\nimport type { GpuBackend, GpuBuffer, GpuProgram, GpuResource, BufferSpec, DrawSpec, UniformValue } from \"./types.js\";\n\ntype ReglGpuBuffer = GpuBuffer & {\n readonly buffer: ReglBuffer;\n};\n\ntype ReglGpuProgram = GpuProgram & {\n readonly id: number;\n readonly vert: string;\n readonly frag: string;\n};\n\ninterface DrawProps {\n readonly count: number;\n readonly instances: number;\n readonly attributes: Readonly<Record<string, ReglBuffer>>;\n readonly uniforms: Readonly<Record<string, UniformValue>>;\n}\n\nfunction toReglContext(gl: WebGL2RenderingContext): WebGLRenderingContext {\n // regl's public types accept WebGLRenderingContext even though regl can run on WebGL2 contexts.\n return gl as unknown as WebGLRenderingContext;\n}\n\nexport class ReglBackend implements GpuBackend {\n private gl: WebGL2RenderingContext;\n private regl: Regl;\n private nextProgramId: number = 1;\n private commandCache: Map<string, DrawCommand> = new Map();\n\n constructor(canvas: HTMLCanvasElement) {\n const gl = canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!gl) {\n throw new Error(\"BlazePlot requires WebGL2, but this browser/context does not support it.\");\n }\n\n this.gl = gl;\n this.regl = createRegl({\n gl: toReglContext(this.gl),\n extensions: [],\n optionalExtensions: [\n \"ext_disjoint_timer_query_webgl2\",\n ],\n });\n }\n\n createBuffer(spec: BufferSpec): GpuBuffer {\n const bytesPerElement = spec.type === \"float\" ? 4 : 2;\n return {\n length: spec.length,\n type: spec.type,\n buffer: this.regl.buffer({\n length: spec.length * bytesPerElement,\n usage: spec.usage,\n type: spec.type === \"float\" ? \"float\" : \"uint16\",\n }),\n } as ReglGpuBuffer;\n }\n\n updateBuffer(buffer: GpuBuffer, data: Float32Array | Uint16Array, offset: number = 0): void {\n if (data.length + offset > buffer.length) {\n throw new RangeError(\"GPU buffer update exceeds allocated buffer length.\");\n }\n\n const bytesPerElement = buffer.type === \"float\" ? 4 : 2;\n this.asReglBuffer(buffer).buffer.subdata(data, offset * bytesPerElement);\n }\n\n createProgram(vert: string, frag: string): GpuProgram {\n return {\n id: this.nextProgramId++,\n vert,\n frag,\n } as ReglGpuProgram;\n }\n\n draw(spec: DrawSpec): void {\n if (spec.count <= 0) return;\n\n const program = this.asReglProgram(spec.program);\n const attributeNames = Object.keys(spec.attributes).sort();\n const uniformNames = Object.keys(spec.uniforms).sort();\n const key = [program.id, spec.primitive, attributeNames.join(\",\"), uniformNames.join(\",\"), spec.instances === undefined ? 0 : 1].join(\"|\");\n let command = this.commandCache.get(key);\n\n if (!command) {\n command = this.createDrawCommand(program, spec.primitive, attributeNames, uniformNames, spec.instances !== undefined);\n this.commandCache.set(key, command);\n }\n\n const attributes: Record<string, ReglBuffer> = {};\n for (const name of attributeNames) {\n attributes[name] = this.asReglBuffer(spec.attributes[name]!).buffer;\n }\n\n command({\n count: spec.count,\n instances: spec.instances ?? 0,\n attributes,\n uniforms: spec.uniforms,\n });\n }\n\n dispose(resource: GpuResource): void {\n if (this.isReglBuffer(resource)) resource.buffer.destroy();\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.regl.clear({ color: [r, g, b, a] });\n }\n\n viewport(_x: number, _y: number, _w: number, _h: number): void {\n // Handled by regl internally via canvas size\n }\n\n destroy(): void {\n this.regl.destroy();\n }\n\n private createDrawCommand(\n program: ReglGpuProgram,\n primitive: DrawSpec[\"primitive\"],\n attributeNames: readonly string[],\n uniformNames: readonly string[],\n instanced: boolean,\n ): DrawCommand {\n const attributes: Record<string, (context: object, props: DrawProps) => AttributeState> = {};\n for (const name of attributeNames) {\n attributes[name] = (_context, props) => props.attributes[name]!;\n }\n\n const uniforms: Record<string, (context: object, props: DrawProps) => Uniform> = {};\n for (const name of uniformNames) {\n uniforms[name] = (_context, props) => props.uniforms[name] as Uniform;\n }\n\n return this.regl({\n vert: program.vert,\n frag: program.frag,\n attributes,\n uniforms,\n primitive: this.toReglPrimitive(primitive),\n count: (_context: object, props: DrawProps) => props.count,\n instances: instanced ? (_context: object, props: DrawProps) => props.instances : undefined,\n depth: { enable: false },\n });\n }\n\n private asReglBuffer(buffer: GpuBuffer): ReglGpuBuffer {\n return buffer as ReglGpuBuffer;\n }\n\n private asReglProgram(program: GpuProgram): ReglGpuProgram {\n return program as ReglGpuProgram;\n }\n\n private isReglBuffer(resource: GpuResource): resource is ReglGpuBuffer {\n return \"length\" in resource && \"type\" in resource && \"buffer\" in resource;\n }\n\n private toReglPrimitive(primitive: DrawSpec[\"primitive\"]): PrimitiveType {\n switch (primitive) {\n case \"line_strip\":\n return \"line strip\";\n case \"triangle_strip\":\n return \"triangle strip\";\n default:\n return primitive;\n }\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\nimport type { PanIntent, ViewportPolicy, ZoomIntent } from \"./types.js\";\n\nexport class InputController {\n private _enabled: boolean = true;\n private activePointerId: number | null = null;\n private lastX: number = 0;\n private lastY: number = 0;\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly camera: Camera2D,\n private readonly policy?: ViewportPolicy,\n ) {\n this.bindEvents();\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n private bindEvents(): void {\n this.canvas.addEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.addEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.addEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.addEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.addEventListener(\"wheel\", this.onWheel, { passive: false });\n }\n\n private onPointerDown = (e: PointerEvent): void => {\n if (!this._enabled || this.activePointerId !== null) return;\n this.activePointerId = e.pointerId;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n this.canvas.setPointerCapture(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this._enabled || e.pointerId !== this.activePointerId) return;\n const rect = this.canvas.getBoundingClientRect();\n const dx = rect.width > 0 ? (this.lastX - e.clientX) / rect.width : 0;\n const dy = rect.height > 0 ? (e.clientY - this.lastY) / rect.height : 0;\n const intent = this.applyPanPolicy({ dx, dy });\n if (intent) this.camera.pan(intent);\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointerId) return;\n this.activePointerId = null;\n if (this.canvas.hasPointerCapture(e.pointerId)) {\n this.canvas.releasePointerCapture(e.pointerId);\n }\n };\n\n private onWheel = (e: WheelEvent): void => {\n if (!this._enabled) return;\n e.preventDefault();\n const factor = e.deltaY < 0 ? 1.1 : 0.9;\n const rect = this.canvas.getBoundingClientRect();\n const cx = rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5;\n const cy = rect.height > 0 ? 1 - (e.clientY - rect.top) / rect.height : 0.5;\n const intent = this.applyZoomPolicy({ factor, cx, cy, axis: \"xy\" });\n if (intent) this.camera.zoom(intent);\n };\n\n private applyPanPolicy(intent: PanIntent): PanIntent | null {\n if (!this.policy?.beforePan) return intent;\n return this.policy.beforePan(this.camera, intent);\n }\n\n private applyZoomPolicy(intent: ZoomIntent): ZoomIntent | null {\n if (!this.policy?.beforeZoom) return intent;\n return this.policy.beforeZoom(this.camera, intent);\n }\n\n dispose(): void {\n this.canvas.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.removeEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.removeEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.removeEventListener(\"wheel\", this.onWheel);\n }\n}\n","import type { Viewport } from \"../core/types.js\";\nimport type { PanIntent, ZoomIntent } from \"./types.js\";\n\nexport class Camera2D {\n private _xMin: number = 0;\n private _xMax: number = 1;\n private _yMin: number = 0;\n private _yMax: number = 1;\n\n get xMin(): number {\n return this._xMin;\n }\n\n get xMax(): number {\n return this._xMax;\n }\n\n get yMin(): number {\n return this._yMin;\n }\n\n get yMax(): number {\n return this._yMax;\n }\n\n get viewport(): Viewport {\n return { xMin: this._xMin, xMax: this._xMax, yMin: this._yMin, yMax: this._yMax };\n }\n\n get xScale(): number {\n return 2 / (this._xMax - this._xMin);\n }\n\n get xOffset(): number {\n return -(this._xMin + this._xMax) / (this._xMax - this._xMin);\n }\n\n get yScale(): number {\n return 2 / (this._yMax - this._yMin);\n }\n\n get yOffset(): number {\n return -(this._yMin + this._yMax) / (this._yMax - this._yMin);\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n const next = {\n xMin: v.xMin ?? this._xMin,\n xMax: v.xMax ?? this._xMax,\n yMin: v.yMin ?? this._yMin,\n yMax: v.yMax ?? this._yMax,\n };\n Camera2D.assertValidViewport(next);\n this._xMin = next.xMin;\n this._xMax = next.xMax;\n this._yMin = next.yMin;\n this._yMax = next.yMax;\n }\n\n pan(intent: PanIntent): void {\n const { dx, dy } = intent;\n Camera2D.assertFinite(\"dx\", dx);\n Camera2D.assertFinite(\"dy\", dy);\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n this.setViewport({\n xMin: this._xMin + dx * rangeX,\n xMax: this._xMax + dx * rangeX,\n yMin: this._yMin + dy * rangeY,\n yMax: this._yMax + dy * rangeY,\n });\n }\n\n zoom(intent: ZoomIntent): void {\n const { factor, cx, cy, axis } = intent;\n Camera2D.assertFinite(\"factor\", factor);\n Camera2D.assertFinite(\"cx\", cx);\n Camera2D.assertFinite(\"cy\", cy);\n if (factor <= 0) throw new RangeError(\"Camera2D zoom factor must be > 0.\");\n\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n const dataCx = this._xMin + rangeX * cx;\n const dataCy = this._yMin + rangeY * cy;\n const newRangeX = axis === \"y\" ? rangeX : rangeX / factor;\n const newRangeY = axis === \"x\" ? rangeY : rangeY / factor;\n this.setViewport({\n xMin: dataCx - newRangeX * cx,\n xMax: dataCx + newRangeX * (1 - cx),\n yMin: dataCy - newRangeY * cy,\n yMax: dataCy + newRangeY * (1 - cy),\n });\n }\n\n toClip(x: number, y: number): [number, number] {\n return [\n x * this.xScale + this.xOffset,\n y * this.yScale + this.yOffset,\n ];\n }\n\n toScreen(clipX: number, clipY: number, canvasWidth: number, canvasHeight: number): [number, number] {\n return [\n (clipX + 1) * 0.5 * canvasWidth,\n (1 - clipY) * 0.5 * canvasHeight,\n ];\n }\n\n clone(): Camera2D {\n const c = new Camera2D();\n c.setViewport(this.viewport);\n return c;\n }\n\n private static assertValidViewport(v: Viewport): void {\n Camera2D.assertFinite(\"xMin\", v.xMin);\n Camera2D.assertFinite(\"xMax\", v.xMax);\n Camera2D.assertFinite(\"yMin\", v.yMin);\n Camera2D.assertFinite(\"yMax\", v.yMax);\n if (v.xMax <= v.xMin) throw new RangeError(\"Camera2D requires xMax > xMin.\");\n if (v.yMax <= v.yMin) throw new RangeError(\"Camera2D requires yMax > yMin.\");\n }\n\n private static assertFinite(name: string, value: number): void {\n if (!Number.isFinite(value)) throw new RangeError(`Camera2D ${name} must be finite.`);\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\n\nexport class AxisController {\n constructor(private readonly camera: Camera2D) {}\n\n getXTickValues(canvasWidth: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.xMin, this.camera.xMax, canvasWidth, maxTicks, 80, target);\n }\n\n getYTickValues(canvasHeight: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.yMin, this.camera.yMax, canvasHeight, maxTicks, 48, target);\n }\n\n formatValue(value: number): string {\n if (Math.abs(value) < 1e-12) return \"0\";\n const abs = Math.abs(value);\n if (abs >= 1e6 || abs < 1e-3) return value.toExponential(2);\n if (abs >= 100) return value.toFixed(0);\n if (abs >= 10) return value.toFixed(1);\n return value.toFixed(2);\n }\n\n private getTickValues(min: number, max: number, pixelSize: number, maxTicks: number, minPixelSpacing: number, target: number[]): number[] {\n target.length = 0;\n if (pixelSize <= 0 || maxTicks <= 0) return target;\n\n const range = max - min;\n if (!Number.isFinite(range) || range <= 0) return target;\n\n const targetTicks = Math.max(2, Math.min(maxTicks, Math.floor(pixelSize / minPixelSpacing)));\n const step = this.niceStep(range / (targetTicks - 1));\n const firstIndex = Math.floor(min / step);\n const lastIndex = Math.ceil(max / step);\n\n for (let index = firstIndex; index <= lastIndex && target.length < maxTicks + 2; index++) {\n target.push(this.normalizeTick(index * step, step));\n }\n\n return target;\n }\n\n private niceStep(rawStep: number): number {\n const magnitude = 10 ** Math.floor(Math.log10(rawStep));\n const normalized = rawStep / magnitude;\n\n if (normalized <= 1.5) return magnitude;\n if (normalized <= 3) return 2 * magnitude;\n if (normalized <= 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n\n private normalizeTick(value: number, step: number): number {\n const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 2);\n const normalized = Number(value.toFixed(decimals));\n return Object.is(normalized, -0) ? 0 : normalized;\n }\n}\n","import type { SeriesConfig, SeriesStyle } from \"../core/types.js\";\nimport { SeriesStore } from \"../core/SeriesStore.js\";\nimport { Renderer } from \"../render/Renderer.js\";\nimport { ReglBackend } from \"../render/ReglBackend.js\";\nimport type { GpuBuffer } from \"../render/types.js\";\nimport { InputController } from \"../interaction/InputController.js\";\nimport { Camera2D } from \"../interaction/Camera2D.js\";\nimport { AxisController } from \"../interaction/AxisController.js\";\nimport type { ViewportPolicy } from \"../interaction/types.js\";\n\nconst RAW_LINE_VERTEX_CAPACITY = 16_384;\nconst GRID_LINE_VERTEX_CAPACITY = 64;\n\nexport interface ChartOptions {\n readonly viewportPolicy?: ViewportPolicy;\n readonly grid?: boolean;\n readonly gridStyle?: Partial<SeriesStyle>;\n}\n\nexport interface ChartFrameStats {\n fps: number;\n frameMs: number;\n pointsRendered: number;\n drawCalls: number;\n uploadBytes: number;\n renderMode: \"none\" | \"raw\" | \"minmax\" | \"mixed\";\n}\n\nexport class Chart {\n private series: SeriesStore[] = [];\n private camera: Camera2D;\n private axis: AxisController;\n private renderer: Renderer;\n private input: InputController;\n private rawLineBuffer: GpuBuffer;\n private rawLineData: Float32Array;\n private gridBuffer: GpuBuffer;\n private gridData: Float32Array;\n private gridStyle: SeriesStyle;\n private readonly xTicks: number[] = [];\n private readonly yTicks: number[] = [];\n private stats: ChartFrameStats = {\n fps: 0,\n frameMs: 0,\n pointsRendered: 0,\n drawCalls: 0,\n uploadBytes: 0,\n renderMode: \"none\",\n };\n private resizeObserver: ResizeObserver | null = null;\n private lastFrameAt: number = 0;\n private _rafId: number = 0;\n\n constructor(private readonly canvas: HTMLCanvasElement, private readonly options: ChartOptions = {}) {\n this.applyCanvasSize();\n this.camera = new Camera2D();\n this.axis = new AxisController(this.camera);\n this.renderer = new Renderer(new ReglBackend(canvas));\n this.input = new InputController(canvas, this.camera, options.viewportPolicy);\n this.rawLineData = new Float32Array(RAW_LINE_VERTEX_CAPACITY * 2);\n this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length);\n this.gridData = new Float32Array(GRID_LINE_VERTEX_CAPACITY * 2);\n this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length);\n this.gridStyle = {\n color: options.gridStyle?.color ?? [0.22, 0.30, 0.44, 0.45],\n lineWidth: options.gridStyle?.lineWidth ?? 1,\n };\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.canvas);\n }\n }\n\n addSeries(config: SeriesConfig, style?: Partial<SeriesStyle>): SeriesStore {\n const s = new SeriesStore(config, {\n color: style?.color ?? [0.3, 0.6, 1.0, 1.0],\n lineWidth: style?.lineWidth ?? 1,\n });\n this.series.push(s);\n return s;\n }\n\n removeSeries(series: SeriesStore): boolean {\n const index = this.series.indexOf(series);\n if (index === -1) return false;\n\n this.series.splice(index, 1);\n return true;\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n this.camera.setViewport(v);\n }\n\n resize(dpr: number = globalThis.devicePixelRatio): boolean {\n const resized = this.applyCanvasSize(dpr);\n if (resized) {\n this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n return resized;\n }\n\n getFrameStats(target: ChartFrameStats = { fps: 0, frameMs: 0, pointsRendered: 0, drawCalls: 0, uploadBytes: 0, renderMode: \"none\" }): ChartFrameStats {\n target.fps = this.stats.fps;\n target.frameMs = this.stats.frameMs;\n target.pointsRendered = this.stats.pointsRendered;\n target.drawCalls = this.stats.drawCalls;\n target.uploadBytes = this.stats.uploadBytes;\n target.renderMode = this.stats.renderMode;\n return target;\n }\n\n start(): void {\n const frame = (): void => {\n this._rafId = requestAnimationFrame(frame);\n this.render();\n };\n this._rafId = requestAnimationFrame(frame);\n }\n\n stop(): void {\n cancelAnimationFrame(this._rafId);\n }\n\n private render(): void {\n const frameStartedAt = performance.now();\n if (this.lastFrameAt > 0) {\n this.stats.fps = 1000 / (frameStartedAt - this.lastFrameAt);\n }\n this.lastFrameAt = frameStartedAt;\n this.stats.pointsRendered = 0;\n this.stats.drawCalls = 0;\n this.stats.uploadBytes = 0;\n this.stats.renderMode = \"none\";\n\n this.options.viewportPolicy?.beforeRender?.(this.camera);\n this.renderer.clear(0.08, 0.10, 0.16, 1);\n\n const viewport = this.camera.viewport;\n if (this.options.grid !== false) {\n const gridVertexCount = this.writeGridVertices(viewport);\n if (gridVertexCount > 0) {\n this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData);\n this.renderer.drawLines(this.gridBuffer, gridVertexCount, this.gridStyle, this.camera);\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.gridData.byteLength;\n }\n }\n\n for (const s of this.series) {\n if (!s.visible) continue;\n const visibleSamples = s.visibleSampleCount(viewport);\n const dense = visibleSamples > RAW_LINE_VERTEX_CAPACITY;\n const count = dense\n ? s.copyMinMaxVisible(viewport, this.rawLineData, Math.min(this.canvas.width, RAW_LINE_VERTEX_CAPACITY >> 1))\n : s.copyRawVisible(viewport, this.rawLineData, RAW_LINE_VERTEX_CAPACITY);\n if (count < 2) continue;\n this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData);\n if (dense) {\n this.renderer.drawMinMaxSegments(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"minmax\");\n } else {\n this.renderer.drawLineStrip(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"raw\");\n }\n this.stats.pointsRendered += count;\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.rawLineData.byteLength;\n }\n\n this.stats.frameMs = performance.now() - frameStartedAt;\n }\n\n dispose(): void {\n this.stop();\n this.resizeObserver?.disconnect();\n this.input.dispose();\n this.renderer.dispose();\n }\n\n private applyCanvasSize(dpr: number = globalThis.devicePixelRatio): boolean {\n const scale = Number.isFinite(dpr) ? Math.max(1, dpr) : 1;\n const width = Math.max(1, Math.floor(this.canvas.clientWidth * scale));\n const height = Math.max(1, Math.floor(this.canvas.clientHeight * scale));\n if (this.canvas.width === width && this.canvas.height === height) return false;\n\n this.canvas.width = width;\n this.canvas.height = height;\n return true;\n }\n\n private writeGridVertices(viewport: { xMin: number; xMax: number; yMin: number; yMax: number }): number {\n this.axis.getXTickValues(this.canvas.width, 12, this.xTicks);\n this.axis.getYTickValues(this.canvas.height, 8, this.yTicks);\n\n let vertexCount = 0;\n for (const x of this.xTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMin;\n vertexCount++;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMax;\n vertexCount++;\n }\n\n for (const y of this.yTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = viewport.xMin;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n this.gridData[vertexCount * 2] = viewport.xMax;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n }\n\n return vertexCount;\n }\n\n private recordRenderMode(mode: \"raw\" | \"minmax\"): void {\n if (this.stats.renderMode === \"none\") {\n this.stats.renderMode = mode;\n } else if (this.stats.renderMode !== mode) {\n this.stats.renderMode = \"mixed\";\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/core/MinMaxPyramid.ts","../src/core/SeriesStore.ts","../src/core/RingBuffer.ts","../src/render/ShaderPrograms.ts","../src/render/Renderer.ts","../src/render/ReglBackend.ts","../src/interaction/InputController.ts","../src/interaction/Camera2D.ts","../src/interaction/AxisController.ts","../src/ui/Chart.ts","../src/core/StaticDataset.ts"],"sourcesContent":["import type { Dataset, LODView, Viewport } from \"./types.js\";\n\nconst MAX_LEVELS = 16;\n\nexport class MinMaxPyramid {\n private levels: Float32Array[] = [];\n private levelLengths: Uint32Array;\n private levelSampleWidths: Uint32Array;\n\n constructor(readonly bucketSize: number = 2) {\n if (!Number.isInteger(bucketSize) || bucketSize < 2) {\n throw new RangeError(\"MinMaxPyramid bucketSize must be an integer >= 2.\");\n }\n\n this.levelLengths = new Uint32Array(MAX_LEVELS);\n this.levelSampleWidths = new Uint32Array(MAX_LEVELS);\n }\n\n build(source: Dataset): void {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n\n let srcLen = source.length;\n if (srcLen === 0) return;\n\n let prevLevel: Float32Array | null = null;\n let level = 0;\n\n while (srcLen > 0 && level < MAX_LEVELS) {\n const nextLen = Math.ceil(srcLen / this.bucketSize);\n const levelData = new Float32Array(nextLen * 2);\n\n for (let i = 0; i < srcLen; i += this.bucketSize) {\n let minY = Infinity;\n let maxY = -Infinity;\n const end = Math.min(i + this.bucketSize, srcLen);\n for (let j = i; j < end; j++) {\n if (prevLevel) {\n const prevMin = prevLevel[j * 2]!;\n const prevMax = prevLevel[j * 2 + 1]!;\n if (prevMin < minY) minY = prevMin;\n if (prevMax > maxY) maxY = prevMax;\n } else {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n const outIdx = Math.floor(i / this.bucketSize);\n levelData[outIdx * 2] = minY;\n levelData[outIdx * 2 + 1] = maxY;\n }\n\n this.levels[level] = levelData;\n this.levelLengths[level] = nextLen;\n this.levelSampleWidths[level] = this.bucketSize ** (level + 1);\n\n if (nextLen === 1) break;\n\n prevLevel = levelData;\n srcLen = nextLen;\n level++;\n }\n }\n\n query(_viewport: Viewport, pixelWidth: number, xRange: { start: number; length: number }): LODView {\n if (pixelWidth <= 0 || xRange.length <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const visibleSamples = xRange.length;\n const samplesPerPixel = Math.max(1, visibleSamples / pixelWidth);\n const level = Math.min(\n Math.max(0, Math.ceil(Math.log2(samplesPerPixel)) - 1),\n this.levels.length - 1,\n );\n\n const levelData = this.levels[level];\n const levelLen = this.levelLengths[level];\n const sampleWidth = this.levelSampleWidths[level];\n if (!levelData || levelLen === undefined || sampleWidth === undefined || levelLen === 0 || sampleWidth === 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel };\n }\n\n const queryStart = Math.max(0, xRange.start);\n const queryEnd = queryStart + xRange.length;\n const bucketStart = Math.max(0, Math.floor(queryStart / sampleWidth));\n const bucketEnd = Math.min(levelLen, Math.ceil(queryEnd / sampleWidth));\n const count = bucketEnd - bucketStart;\n\n if (count <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level, samplesPerPixel };\n }\n\n const result = new Float32Array(count * 2);\n for (let i = 0; i < count; i++) {\n const j = (bucketStart + i) * 2;\n result[i * 2] = levelData[j]!;\n result[i * 2 + 1] = levelData[j + 1]!;\n }\n\n return { buckets: result, bucketCount: count, level, samplesPerPixel };\n }\n}\n","import type { Dataset, AppendableDataset, LODView, Viewport, SeriesConfig, SeriesStyle } from \"./types.js\";\nimport { MinMaxPyramid } from \"./MinMaxPyramid.js\";\n\nexport class SeriesStore {\n readonly config: SeriesConfig;\n readonly style: SeriesStyle;\n private readonly dataset: Dataset;\n private readonly pyramid: MinMaxPyramid;\n\n private _dirty: boolean = false;\n private _visible: boolean = true;\n\n constructor(dataset: Dataset, config: SeriesConfig, style: SeriesStyle) {\n this.dataset = dataset;\n this.config = config;\n this.pyramid = new MinMaxPyramid();\n this.style = style;\n\n if (dataset.length > 0) {\n this.pyramid.build(dataset);\n }\n }\n\n get dirty(): boolean {\n return this._dirty;\n }\n\n get length(): number {\n return this.dataset.length;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n setVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n if (!(\"push\" in this.dataset)) {\n throw new TypeError(\"SeriesStore dataset is not appendable.\");\n }\n\n const appendable = this.dataset as AppendableDataset;\n appendable.append(x, y);\n this._dirty = true;\n }\n\n clear(): void {\n if (!(\"clear\" in this.dataset)) {\n throw new TypeError(\"SeriesStore dataset is not clearable.\");\n }\n\n (this.dataset as AppendableDataset).clear();\n this.pyramid.build(this.dataset);\n this._dirty = false;\n }\n\n rebuildPyramid(): void {\n if (!this._dirty) return;\n this.pyramid.build(this.dataset);\n this._dirty = false;\n }\n\n query(viewport: Viewport, pixelWidth: number): LODView {\n const range = this.dataset.range;\n if (!range) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n\n return this.pyramid.query(viewport, pixelWidth, {\n start,\n length: Math.max(0, end - start),\n });\n }\n\n visibleSampleCount(viewport: Viewport): number {\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n return Math.max(0, end - start);\n }\n\n copyRawVisible(viewport: Viewport, target: Float32Array, maxPoints: number): number {\n if (maxPoints <= 0 || target.length < maxPoints * 2) return 0;\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const stride = Math.max(1, Math.ceil(visible / maxPoints));\n let count = 0;\n for (let i = start; i < end && count < maxPoints; i += stride) {\n target[count * 2] = this.dataset.getX(i);\n target[count * 2 + 1] = this.dataset.getY(i);\n count++;\n }\n\n return count;\n }\n\n copyMinMaxVisible(viewport: Viewport, target: Float32Array, maxSegments: number): number {\n if (maxSegments <= 0 || target.length < maxSegments * 4) return 0;\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const segmentCount = Math.min(maxSegments, visible);\n let vertexCount = 0;\n for (let segment = 0; segment < segmentCount; segment++) {\n const segmentStart = start + Math.floor((segment * visible) / segmentCount);\n const segmentEnd = start + Math.max(\n Math.floor(((segment + 1) * visible) / segmentCount),\n Math.floor((segment * visible) / segmentCount) + 1,\n );\n const clampedEnd = Math.min(end, segmentEnd);\n\n let minY = Infinity;\n let maxY = -Infinity;\n for (let i = segmentStart; i < clampedEnd; i++) {\n const y = this.dataset.getY(i);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n const x = this.dataset.getX(segmentStart + ((clampedEnd - segmentStart) >> 1));\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = minY;\n vertexCount++;\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = maxY;\n vertexCount++;\n }\n\n return vertexCount;\n }\n}\n","import type { TimeRange } from \"./types.js\";\n\nexport class RingBuffer {\n readonly capacity: number;\n private _length: number = 0;\n private _head: number = 0;\n\n private readonly xData: Float64Array;\n private readonly yData: Float32Array;\n\n constructor(capacity: number) {\n if (!Number.isInteger(capacity) || capacity <= 0) {\n throw new RangeError(\"RingBuffer capacity must be a positive integer.\");\n }\n\n this.capacity = capacity;\n this.xData = new Float64Array(capacity);\n this.yData = new Float32Array(capacity);\n }\n\n get length(): number {\n return this._length;\n }\n\n get range(): TimeRange | null {\n if (this._length === 0) return null;\n return { start: this.getX(0), end: this.getX(this._length - 1) };\n }\n\n push(x: number, y: number): void {\n this.xData[this._head] = x;\n this.yData[this._head] = y;\n this._head = (this._head + 1) % this.capacity;\n if (this._length < this.capacity) this._length++;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n const n = Math.min(x.length, y.length);\n for (let i = 0; i < n; i++) {\n this.push(x[i]!, y[i]!);\n }\n }\n\n get(index: number): { x: number; y: number } | null {\n if (index < 0 || index >= this._length) return null;\n return { x: this.getX(index), y: this.getY(index) };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[this.logicalToPhysical(index)]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[this.logicalToPhysical(index)]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n clear(): void {\n this._length = 0;\n this._head = 0;\n }\n\n private logicalToPhysical(index: number): number {\n return (this._head - this._length + index + this.capacity) % this.capacity;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this._length) {\n throw new RangeError(`RingBuffer index out of range: ${index}`);\n }\n }\n}\n","import lineVert from \"./shaders/line.vert?raw\";\nimport lineFrag from \"./shaders/line.frag?raw\";\nimport segmentVert from \"./shaders/segment.vert?raw\";\nimport segmentFrag from \"./shaders/segment.frag?raw\";\n\nexport const ShaderPrograms = {\n line: { vert: lineVert, frag: lineFrag },\n segment: { vert: segmentVert, frag: segmentFrag },\n} as const;\n","import { ShaderPrograms } from \"./ShaderPrograms.js\";\nimport type { Camera2D } from \"../interaction/Camera2D.js\";\nimport type { GpuBackend, GpuBuffer, GpuProgram } from \"./types.js\";\nimport type { SeriesStyle } from \"../core/types.js\";\n\nexport class Renderer {\n private readonly lineProgram: GpuProgram;\n private readonly scaleUniform: Float32Array = new Float32Array(2);\n private readonly offsetUniform: Float32Array = new Float32Array(2);\n\n constructor(private backend: GpuBackend) {\n this.lineProgram = this.backend.createProgram(ShaderPrograms.line.vert, ShaderPrograms.line.frag);\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.backend.clear(r, g, b, a);\n }\n\n createFloatBuffer(floatCount: number): GpuBuffer {\n return this.backend.createBuffer({ usage: \"stream\", type: \"float\", length: floatCount });\n }\n\n updateFloatBuffer(buffer: GpuBuffer, data: Float32Array): void {\n this.backend.updateBuffer(buffer, data);\n }\n\n viewport(x: number, y: number, width: number, height: number): void {\n this.backend.viewport(x, y, width, height);\n }\n\n drawLines(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"lines\", positions, count, style, camera);\n }\n\n drawLineStrip(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"line_strip\", positions, count, style, camera);\n }\n\n private drawLinePrimitive(primitive: \"lines\" | \"line_strip\", positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.scaleUniform[0] = camera.xScale;\n this.scaleUniform[1] = camera.yScale;\n this.offsetUniform[0] = camera.xOffset;\n this.offsetUniform[1] = camera.yOffset;\n\n this.backend.draw({\n program: this.lineProgram,\n primitive,\n count,\n attributes: { position: positions },\n uniforms: {\n uScale: this.scaleUniform,\n uOffset: this.offsetUniform,\n uColor: style.color,\n },\n });\n }\n\n drawMinMaxSegments(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLines(positions, count, style, camera);\n }\n\n dispose(): void {\n this.backend.destroy();\n }\n}\n","import createRegl from \"regl\";\nimport type { AttributeState, Buffer as ReglBuffer, DrawCommand, PrimitiveType, Regl, Uniform } from \"regl\";\nimport type { GpuBackend, GpuBuffer, GpuProgram, GpuResource, BufferSpec, DrawSpec, UniformValue } from \"./types.js\";\n\ntype ReglGpuBuffer = GpuBuffer & {\n readonly buffer: ReglBuffer;\n};\n\ntype ReglGpuProgram = GpuProgram & {\n readonly id: number;\n readonly vert: string;\n readonly frag: string;\n};\n\ninterface DrawProps {\n readonly count: number;\n readonly instances: number;\n readonly attributes: Readonly<Record<string, ReglBuffer>>;\n readonly uniforms: Readonly<Record<string, UniformValue>>;\n}\n\nfunction toReglContext(gl: WebGL2RenderingContext): WebGLRenderingContext {\n // regl's public types accept WebGLRenderingContext even though regl can run on WebGL2 contexts.\n return gl as unknown as WebGLRenderingContext;\n}\n\nexport class ReglBackend implements GpuBackend {\n private gl: WebGL2RenderingContext;\n private regl: Regl;\n private nextProgramId: number = 1;\n private commandCache: Map<string, DrawCommand> = new Map();\n\n constructor(canvas: HTMLCanvasElement) {\n const gl = canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!gl) {\n throw new Error(\"BlazePlot requires WebGL2, but this browser/context does not support it.\");\n }\n\n this.gl = gl;\n this.regl = createRegl({\n gl: toReglContext(this.gl),\n extensions: [],\n optionalExtensions: [\n \"ext_disjoint_timer_query_webgl2\",\n ],\n });\n }\n\n createBuffer(spec: BufferSpec): GpuBuffer {\n const bytesPerElement = spec.type === \"float\" ? 4 : 2;\n return {\n length: spec.length,\n type: spec.type,\n buffer: this.regl.buffer({\n length: spec.length * bytesPerElement,\n usage: spec.usage,\n type: spec.type === \"float\" ? \"float\" : \"uint16\",\n }),\n } as ReglGpuBuffer;\n }\n\n updateBuffer(buffer: GpuBuffer, data: Float32Array | Uint16Array, offset: number = 0): void {\n if (data.length + offset > buffer.length) {\n throw new RangeError(\"GPU buffer update exceeds allocated buffer length.\");\n }\n\n const bytesPerElement = buffer.type === \"float\" ? 4 : 2;\n this.asReglBuffer(buffer).buffer.subdata(data, offset * bytesPerElement);\n }\n\n createProgram(vert: string, frag: string): GpuProgram {\n return {\n id: this.nextProgramId++,\n vert,\n frag,\n } as ReglGpuProgram;\n }\n\n draw(spec: DrawSpec): void {\n if (spec.count <= 0) return;\n\n const program = this.asReglProgram(spec.program);\n const attributeNames = Object.keys(spec.attributes).sort();\n const uniformNames = Object.keys(spec.uniforms).sort();\n const key = [program.id, spec.primitive, attributeNames.join(\",\"), uniformNames.join(\",\"), spec.instances === undefined ? 0 : 1].join(\"|\");\n let command = this.commandCache.get(key);\n\n if (!command) {\n command = this.createDrawCommand(program, spec.primitive, attributeNames, uniformNames, spec.instances !== undefined);\n this.commandCache.set(key, command);\n }\n\n const attributes: Record<string, ReglBuffer> = {};\n for (const name of attributeNames) {\n attributes[name] = this.asReglBuffer(spec.attributes[name]!).buffer;\n }\n\n command({\n count: spec.count,\n instances: spec.instances ?? 0,\n attributes,\n uniforms: spec.uniforms,\n });\n }\n\n dispose(resource: GpuResource): void {\n if (this.isReglBuffer(resource)) resource.buffer.destroy();\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.regl.clear({ color: [r, g, b, a] });\n }\n\n viewport(_x: number, _y: number, _w: number, _h: number): void {\n // Handled by regl internally via canvas size\n }\n\n destroy(): void {\n this.regl.destroy();\n }\n\n private createDrawCommand(\n program: ReglGpuProgram,\n primitive: DrawSpec[\"primitive\"],\n attributeNames: readonly string[],\n uniformNames: readonly string[],\n instanced: boolean,\n ): DrawCommand {\n const attributes: Record<string, (context: object, props: DrawProps) => AttributeState> = {};\n for (const name of attributeNames) {\n attributes[name] = (_context, props) => props.attributes[name]!;\n }\n\n const uniforms: Record<string, (context: object, props: DrawProps) => Uniform> = {};\n for (const name of uniformNames) {\n uniforms[name] = (_context, props) => props.uniforms[name] as Uniform;\n }\n\n return this.regl({\n vert: program.vert,\n frag: program.frag,\n attributes,\n uniforms,\n primitive: this.toReglPrimitive(primitive),\n count: (_context: object, props: DrawProps) => props.count,\n instances: instanced ? (_context: object, props: DrawProps) => props.instances : undefined,\n depth: { enable: false },\n });\n }\n\n private asReglBuffer(buffer: GpuBuffer): ReglGpuBuffer {\n return buffer as ReglGpuBuffer;\n }\n\n private asReglProgram(program: GpuProgram): ReglGpuProgram {\n return program as ReglGpuProgram;\n }\n\n private isReglBuffer(resource: GpuResource): resource is ReglGpuBuffer {\n return \"length\" in resource && \"type\" in resource && \"buffer\" in resource;\n }\n\n private toReglPrimitive(primitive: DrawSpec[\"primitive\"]): PrimitiveType {\n switch (primitive) {\n case \"line_strip\":\n return \"line strip\";\n case \"triangle_strip\":\n return \"triangle strip\";\n default:\n return primitive;\n }\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\nimport type { PanIntent, ViewportPolicy, ZoomIntent } from \"./types.js\";\n\nexport class InputController {\n private _enabled: boolean = true;\n private activePointerId: number | null = null;\n private lastX: number = 0;\n private lastY: number = 0;\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly camera: Camera2D,\n private readonly policy?: ViewportPolicy,\n ) {\n this.bindEvents();\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n private bindEvents(): void {\n this.canvas.addEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.addEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.addEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.addEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.addEventListener(\"wheel\", this.onWheel, { passive: false });\n }\n\n private onPointerDown = (e: PointerEvent): void => {\n if (!this._enabled || this.activePointerId !== null) return;\n this.activePointerId = e.pointerId;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n this.canvas.setPointerCapture(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this._enabled || e.pointerId !== this.activePointerId) return;\n const rect = this.canvas.getBoundingClientRect();\n const dx = rect.width > 0 ? (this.lastX - e.clientX) / rect.width : 0;\n const dy = rect.height > 0 ? (e.clientY - this.lastY) / rect.height : 0;\n const intent = this.applyPanPolicy({ dx, dy });\n if (intent) this.camera.pan(intent);\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointerId) return;\n this.activePointerId = null;\n if (this.canvas.hasPointerCapture(e.pointerId)) {\n this.canvas.releasePointerCapture(e.pointerId);\n }\n };\n\n private onWheel = (e: WheelEvent): void => {\n if (!this._enabled) return;\n e.preventDefault();\n const factor = e.deltaY < 0 ? 1.1 : 0.9;\n const rect = this.canvas.getBoundingClientRect();\n const cx = rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5;\n const cy = rect.height > 0 ? 1 - (e.clientY - rect.top) / rect.height : 0.5;\n const intent = this.applyZoomPolicy({ factor, cx, cy, axis: \"xy\" });\n if (intent) this.camera.zoom(intent);\n };\n\n private applyPanPolicy(intent: PanIntent): PanIntent | null {\n if (!this.policy?.beforePan) return intent;\n return this.policy.beforePan(this.camera, intent);\n }\n\n private applyZoomPolicy(intent: ZoomIntent): ZoomIntent | null {\n if (!this.policy?.beforeZoom) return intent;\n return this.policy.beforeZoom(this.camera, intent);\n }\n\n dispose(): void {\n this.canvas.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.removeEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.removeEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.removeEventListener(\"wheel\", this.onWheel);\n }\n}\n","import type { Viewport } from \"../core/types.js\";\nimport type { PanIntent, ZoomIntent } from \"./types.js\";\n\nexport class Camera2D {\n private _xMin: number = 0;\n private _xMax: number = 1;\n private _yMin: number = 0;\n private _yMax: number = 1;\n\n get xMin(): number {\n return this._xMin;\n }\n\n get xMax(): number {\n return this._xMax;\n }\n\n get yMin(): number {\n return this._yMin;\n }\n\n get yMax(): number {\n return this._yMax;\n }\n\n get viewport(): Viewport {\n return { xMin: this._xMin, xMax: this._xMax, yMin: this._yMin, yMax: this._yMax };\n }\n\n get xScale(): number {\n return 2 / (this._xMax - this._xMin);\n }\n\n get xOffset(): number {\n return -(this._xMin + this._xMax) / (this._xMax - this._xMin);\n }\n\n get yScale(): number {\n return 2 / (this._yMax - this._yMin);\n }\n\n get yOffset(): number {\n return -(this._yMin + this._yMax) / (this._yMax - this._yMin);\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n const next = {\n xMin: v.xMin ?? this._xMin,\n xMax: v.xMax ?? this._xMax,\n yMin: v.yMin ?? this._yMin,\n yMax: v.yMax ?? this._yMax,\n };\n Camera2D.assertValidViewport(next);\n this._xMin = next.xMin;\n this._xMax = next.xMax;\n this._yMin = next.yMin;\n this._yMax = next.yMax;\n }\n\n pan(intent: PanIntent): void {\n const { dx, dy } = intent;\n Camera2D.assertFinite(\"dx\", dx);\n Camera2D.assertFinite(\"dy\", dy);\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n this.setViewport({\n xMin: this._xMin + dx * rangeX,\n xMax: this._xMax + dx * rangeX,\n yMin: this._yMin + dy * rangeY,\n yMax: this._yMax + dy * rangeY,\n });\n }\n\n zoom(intent: ZoomIntent): void {\n const { factor, cx, cy, axis } = intent;\n Camera2D.assertFinite(\"factor\", factor);\n Camera2D.assertFinite(\"cx\", cx);\n Camera2D.assertFinite(\"cy\", cy);\n if (factor <= 0) throw new RangeError(\"Camera2D zoom factor must be > 0.\");\n\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n const dataCx = this._xMin + rangeX * cx;\n const dataCy = this._yMin + rangeY * cy;\n const newRangeX = axis === \"y\" ? rangeX : rangeX / factor;\n const newRangeY = axis === \"x\" ? rangeY : rangeY / factor;\n this.setViewport({\n xMin: dataCx - newRangeX * cx,\n xMax: dataCx + newRangeX * (1 - cx),\n yMin: dataCy - newRangeY * cy,\n yMax: dataCy + newRangeY * (1 - cy),\n });\n }\n\n toClip(x: number, y: number): [number, number] {\n return [\n x * this.xScale + this.xOffset,\n y * this.yScale + this.yOffset,\n ];\n }\n\n toScreen(clipX: number, clipY: number, canvasWidth: number, canvasHeight: number): [number, number] {\n return [\n (clipX + 1) * 0.5 * canvasWidth,\n (1 - clipY) * 0.5 * canvasHeight,\n ];\n }\n\n clone(): Camera2D {\n const c = new Camera2D();\n c.setViewport(this.viewport);\n return c;\n }\n\n private static assertValidViewport(v: Viewport): void {\n Camera2D.assertFinite(\"xMin\", v.xMin);\n Camera2D.assertFinite(\"xMax\", v.xMax);\n Camera2D.assertFinite(\"yMin\", v.yMin);\n Camera2D.assertFinite(\"yMax\", v.yMax);\n if (v.xMax <= v.xMin) throw new RangeError(\"Camera2D requires xMax > xMin.\");\n if (v.yMax <= v.yMin) throw new RangeError(\"Camera2D requires yMax > yMin.\");\n }\n\n private static assertFinite(name: string, value: number): void {\n if (!Number.isFinite(value)) throw new RangeError(`Camera2D ${name} must be finite.`);\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\n\nexport class AxisController {\n constructor(private readonly camera: Camera2D) {}\n\n getXTickValues(canvasWidth: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.xMin, this.camera.xMax, canvasWidth, maxTicks, 80, target);\n }\n\n getYTickValues(canvasHeight: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.yMin, this.camera.yMax, canvasHeight, maxTicks, 48, target);\n }\n\n formatValue(value: number): string {\n if (Math.abs(value) < 1e-12) return \"0\";\n const abs = Math.abs(value);\n if (abs >= 1e6 || abs < 1e-3) return value.toExponential(2);\n if (abs >= 100) return value.toFixed(0);\n if (abs >= 10) return value.toFixed(1);\n return value.toFixed(2);\n }\n\n private getTickValues(min: number, max: number, pixelSize: number, maxTicks: number, minPixelSpacing: number, target: number[]): number[] {\n target.length = 0;\n if (pixelSize <= 0 || maxTicks <= 0) return target;\n\n const range = max - min;\n if (!Number.isFinite(range) || range <= 0) return target;\n\n const targetTicks = Math.max(2, Math.min(maxTicks, Math.floor(pixelSize / minPixelSpacing)));\n const step = this.niceStep(range / (targetTicks - 1));\n const firstIndex = Math.floor(min / step);\n const lastIndex = Math.ceil(max / step);\n\n for (let index = firstIndex; index <= lastIndex && target.length < maxTicks + 2; index++) {\n target.push(this.normalizeTick(index * step, step));\n }\n\n return target;\n }\n\n private niceStep(rawStep: number): number {\n const magnitude = 10 ** Math.floor(Math.log10(rawStep));\n const normalized = rawStep / magnitude;\n\n if (normalized <= 1.5) return magnitude;\n if (normalized <= 3) return 2 * magnitude;\n if (normalized <= 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n\n private normalizeTick(value: number, step: number): number {\n const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 2);\n const normalized = Number(value.toFixed(decimals));\n return Object.is(normalized, -0) ? 0 : normalized;\n }\n}\n","import type { SeriesConfig, SeriesStyle, Dataset } from \"../core/types.js\";\nimport { SeriesStore } from \"../core/SeriesStore.js\";\nimport { RingBuffer } from \"../core/RingBuffer.js\";\nimport { Renderer } from \"../render/Renderer.js\";\nimport { ReglBackend } from \"../render/ReglBackend.js\";\nimport type { GpuBuffer } from \"../render/types.js\";\nimport { InputController } from \"../interaction/InputController.js\";\nimport { Camera2D } from \"../interaction/Camera2D.js\";\nimport { AxisController } from \"../interaction/AxisController.js\";\nimport type { ViewportPolicy } from \"../interaction/types.js\";\n\nconst RAW_LINE_VERTEX_CAPACITY = 16_384;\nconst GRID_LINE_VERTEX_CAPACITY = 64;\n\nexport interface ChartOptions {\n readonly viewportPolicy?: ViewportPolicy;\n readonly grid?: boolean;\n readonly gridStyle?: Partial<SeriesStyle>;\n}\n\nexport interface ChartFrameStats {\n fps: number;\n frameMs: number;\n pointsRendered: number;\n drawCalls: number;\n uploadBytes: number;\n renderMode: \"none\" | \"raw\" | \"minmax\" | \"mixed\";\n}\n\nexport class Chart {\n private series: SeriesStore[] = [];\n private camera: Camera2D;\n private axis: AxisController;\n private renderer: Renderer;\n private input: InputController;\n private rawLineBuffer: GpuBuffer;\n private rawLineData: Float32Array;\n private gridBuffer: GpuBuffer;\n private gridData: Float32Array;\n private gridStyle: SeriesStyle;\n private readonly xTicks: number[] = [];\n private readonly yTicks: number[] = [];\n private stats: ChartFrameStats = {\n fps: 0,\n frameMs: 0,\n pointsRendered: 0,\n drawCalls: 0,\n uploadBytes: 0,\n renderMode: \"none\",\n };\n private resizeObserver: ResizeObserver | null = null;\n private lastFrameAt: number = 0;\n private _rafId: number = 0;\n\n constructor(private readonly canvas: HTMLCanvasElement, private readonly options: ChartOptions = {}) {\n this.applyCanvasSize();\n this.camera = new Camera2D();\n this.axis = new AxisController(this.camera);\n this.renderer = new Renderer(new ReglBackend(canvas));\n this.input = new InputController(canvas, this.camera, options.viewportPolicy);\n this.rawLineData = new Float32Array(RAW_LINE_VERTEX_CAPACITY * 2);\n this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length);\n this.gridData = new Float32Array(GRID_LINE_VERTEX_CAPACITY * 2);\n this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length);\n this.gridStyle = {\n color: options.gridStyle?.color ?? [0.22, 0.30, 0.44, 0.45],\n lineWidth: options.gridStyle?.lineWidth ?? 1,\n };\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.canvas);\n }\n }\n\n addSeries(config: SeriesConfig, style?: Partial<SeriesStyle>): SeriesStore {\n const dataset: Dataset = config.dataset ?? new RingBuffer(config.capacity);\n const s = new SeriesStore(dataset, config, {\n color: style?.color ?? [0.3, 0.6, 1.0, 1.0],\n lineWidth: style?.lineWidth ?? 1,\n });\n this.series.push(s);\n return s;\n }\n\n removeSeries(series: SeriesStore): boolean {\n const index = this.series.indexOf(series);\n if (index === -1) return false;\n\n this.series.splice(index, 1);\n return true;\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n this.camera.setViewport(v);\n }\n\n resize(dpr: number = globalThis.devicePixelRatio): boolean {\n const resized = this.applyCanvasSize(dpr);\n if (resized) {\n this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n return resized;\n }\n\n getFrameStats(target: ChartFrameStats = { fps: 0, frameMs: 0, pointsRendered: 0, drawCalls: 0, uploadBytes: 0, renderMode: \"none\" }): ChartFrameStats {\n target.fps = this.stats.fps;\n target.frameMs = this.stats.frameMs;\n target.pointsRendered = this.stats.pointsRendered;\n target.drawCalls = this.stats.drawCalls;\n target.uploadBytes = this.stats.uploadBytes;\n target.renderMode = this.stats.renderMode;\n return target;\n }\n\n start(): void {\n const frame = (): void => {\n this._rafId = requestAnimationFrame(frame);\n this.render();\n };\n this._rafId = requestAnimationFrame(frame);\n }\n\n stop(): void {\n cancelAnimationFrame(this._rafId);\n }\n\n private render(): void {\n const frameStartedAt = performance.now();\n if (this.lastFrameAt > 0) {\n this.stats.fps = 1000 / (frameStartedAt - this.lastFrameAt);\n }\n this.lastFrameAt = frameStartedAt;\n this.stats.pointsRendered = 0;\n this.stats.drawCalls = 0;\n this.stats.uploadBytes = 0;\n this.stats.renderMode = \"none\";\n\n this.options.viewportPolicy?.beforeRender?.(this.camera);\n this.renderer.clear(0.08, 0.10, 0.16, 1);\n\n const viewport = this.camera.viewport;\n if (this.options.grid !== false) {\n const gridVertexCount = this.writeGridVertices(viewport);\n if (gridVertexCount > 0) {\n this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData);\n this.renderer.drawLines(this.gridBuffer, gridVertexCount, this.gridStyle, this.camera);\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.gridData.byteLength;\n }\n }\n\n for (const s of this.series) {\n if (!s.visible) continue;\n const visibleSamples = s.visibleSampleCount(viewport);\n const dense = visibleSamples > RAW_LINE_VERTEX_CAPACITY;\n const count = dense\n ? s.copyMinMaxVisible(viewport, this.rawLineData, Math.min(this.canvas.width, RAW_LINE_VERTEX_CAPACITY >> 1))\n : s.copyRawVisible(viewport, this.rawLineData, RAW_LINE_VERTEX_CAPACITY);\n if (count < 2) continue;\n this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData);\n if (dense) {\n this.renderer.drawMinMaxSegments(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"minmax\");\n } else {\n this.renderer.drawLineStrip(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"raw\");\n }\n this.stats.pointsRendered += count;\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.rawLineData.byteLength;\n }\n\n this.stats.frameMs = performance.now() - frameStartedAt;\n }\n\n dispose(): void {\n this.stop();\n this.resizeObserver?.disconnect();\n this.input.dispose();\n this.renderer.dispose();\n }\n\n private applyCanvasSize(dpr: number = globalThis.devicePixelRatio): boolean {\n const scale = Number.isFinite(dpr) ? Math.max(1, dpr) : 1;\n const width = Math.max(1, Math.floor(this.canvas.clientWidth * scale));\n const height = Math.max(1, Math.floor(this.canvas.clientHeight * scale));\n if (this.canvas.width === width && this.canvas.height === height) return false;\n\n this.canvas.width = width;\n this.canvas.height = height;\n return true;\n }\n\n private writeGridVertices(viewport: { xMin: number; xMax: number; yMin: number; yMax: number }): number {\n this.axis.getXTickValues(this.canvas.width, 12, this.xTicks);\n this.axis.getYTickValues(this.canvas.height, 8, this.yTicks);\n\n let vertexCount = 0;\n for (const x of this.xTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMin;\n vertexCount++;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMax;\n vertexCount++;\n }\n\n for (const y of this.yTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = viewport.xMin;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n this.gridData[vertexCount * 2] = viewport.xMax;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n }\n\n return vertexCount;\n }\n\n private recordRenderMode(mode: \"raw\" | \"minmax\"): void {\n if (this.stats.renderMode === \"none\") {\n this.stats.renderMode = mode;\n } else if (this.stats.renderMode !== mode) {\n this.stats.renderMode = \"mixed\";\n }\n }\n}\n","import type { Dataset, TimeRange } from \"./types.js\";\n\nexport class StaticDataset implements Dataset {\n constructor(\n private readonly xData: ArrayLike<number>,\n private readonly yData: ArrayLike<number>,\n ) {}\n\n get length(): number {\n return Math.min(this.xData.length, this.yData.length);\n }\n\n get range(): TimeRange | null {\n if (this.length === 0) return null;\n return { start: this.xData[0]!, end: this.xData[this.length - 1]! };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[index]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[index]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this.length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.xData[mid]! < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this.length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.xData[mid]! <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this.length) {\n throw new RangeError(`StaticDataset index out of range: ${index}`);\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../../src/ui/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAOrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAK9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;CACjD;AAED,qBAAa,KAAK;IAyBJ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAqB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBhF,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,KAAK,CAOX;IACF,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAa;gBAEE,MAAM,EAAE,iBAAiB,EAAmB,OAAO,GAAE,YAAiB;IAoBnG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW;IAS1E,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAQ1C,WAAW,CAAC,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIpF,MAAM,CAAC,GAAG,GAAE,MAAoC,GAAG,OAAO;IAQ1D,aAAa,CAAC,MAAM,GAAE,eAA6G,GAAG,eAAe;IAUrJ,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAIZ,OAAO,CAAC,MAAM;IAiDd,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,gBAAgB;CAOzB"}
1
+ {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../../src/ui/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAW,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAK9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;CACjD;AAED,qBAAa,KAAK;IAyBJ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAqB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBhF,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,KAAK,CAOX;IACF,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAa;gBAEE,MAAM,EAAE,iBAAiB,EAAmB,OAAO,GAAE,YAAiB;IAoBnG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW;IAU1E,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAQ1C,WAAW,CAAC,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIpF,MAAM,CAAC,GAAG,GAAE,MAAoC,GAAG,OAAO;IAQ1D,aAAa,CAAC,MAAM,GAAE,eAA6G,GAAG,eAAe;IAUrJ,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAIZ,OAAO,CAAC,MAAM;IAiDd,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,gBAAgB;CAOzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blazeplot",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "author": {
5
5
  "name": "BlazePlot contributors"
6
6
  },
@@ -25,8 +25,7 @@
25
25
  "files": [
26
26
  "dist",
27
27
  "README.md",
28
- "LICENSE",
29
- "ROADMAP.md"
28
+ "LICENSE"
30
29
  ],
31
30
  "scripts": {
32
31
  "dev": "vite",
package/ROADMAP.md DELETED
@@ -1,263 +0,0 @@
1
- # BlazePlot — Roadmap
2
-
3
- **BlazePlot is a real-time LOD time series rendering engine, not a plotting library.**
4
-
5
- Target: 10M points resident, 60 Hz append/update, pan/zoom fluid, render O(pixel) not O(samples), zero allocations in frame loop, multi-series, line/envelope/scatter.
6
-
7
- ---
8
-
9
- ## Architecture
10
-
11
- ```
12
- src/
13
- core/ # Data engine — no UI, no GPU
14
- render/ # GPU abstraction + regl V1 backend
15
- interaction/ # Camera, input, axis ticks
16
- ui/ # Orchestrator (Chart)
17
- tests/ # bun test — RingBuffer, MinMaxPyramid, Camera2D
18
- preview/ # Dev preview harness, detached from package build
19
- ```
20
-
21
- The core split: **data engine** and **renderer** are separate. A `SeriesStore` owns a `RingBuffer` + `MinMaxPyramid`. The renderer reads LOD views, never raw data.
22
-
23
- ```
24
- interface GpuBackend { … } # abstract GPU
25
- class ReglBackend { … } # V1 implementation
26
- class FutureWebGPUBackend { …} # V3
27
- ```
28
-
29
- **Camera2D** is the canonical viewport model (data-space xMin/xMax/yMin/yMax). Scale/offset for shader uniforms are derived getters. `ViewportPlanner` was removed — its pan/zoom live on `Camera2D` directly.
30
-
31
- Package output is detached from the preview app:
32
- - `bun run dev` serves `preview/`.
33
- - `bun run build` emits `dist/index.js` and `dist/index.d.ts` from `src/index.ts`.
34
- - `preview/` is excluded from npm package contents.
35
-
36
- ---
37
-
38
- ## Phase 1 — Vertical slice: line on screen
39
-
40
- **Status: in progress**
41
-
42
- Get one end-to-end path working: append → visible raw extraction → GPU upload → draw.
43
-
44
- - [x] WebGL2 context + regl init
45
- - [x] Canvas resize + DPR handling
46
- - [x] Streaming append with debug overlay
47
- - [x] `ReglBackend` — createBuffer, updateBuffer, createProgram, cached draw commands
48
- - [x] Raw line strip draw via regl
49
- - [x] Wire `Chart.render()`: clear → copy visible raw range → upload → draw
50
- - [x] **Benchmark overlay**: fps, ms/frame, points rendered, draw calls, upload bytes
51
-
52
- This is the shortest path to seeing data on screen. Benchmarking the full pipeline comes after.
53
-
54
- ---
55
-
56
- ## Phase 2 — Core data engine
57
-
58
- **Status: basic scaffold implemented, correctness tests passing**
59
-
60
- - [x] `RingBuffer` — append-only, Float64Array x / Float32Array y, logical index access, ring-wrap aware search
61
- - [x] `MinMaxPyramid` — min/max per level (bucket size 2), correct higher-level aggregation, ring-wrap aware builds, `query()` returns `LODView`
62
- - [x] `SeriesStore` — buffer + pyramid + style, dirty tracking
63
- - [x] `Camera2D` — viewport model with pan, zoom, setViewport, clip/screen transforms
64
- - [x] `DataCursor` — binary search by timestamp
65
- - [x] Tests for `RingBuffer`, `MinMaxPyramid`, and `Camera2D` (bun test runner)
66
- - [ ] **Incremental pyramid update** — current: full rebuild on every `build()`. Target: O(log N) per append, updating only closed buckets in the chain. This is the core competitive advantage — must be designed before release.
67
-
68
- ---
69
-
70
- ## Phase 2.5 — Worker pipeline
71
-
72
- **Status: not started**
73
-
74
- ```
75
- producer thread / worker ──► SharedArrayBuffer ──► downsampling worker ──► main thread
76
- ```
77
-
78
- - [ ] Ingest worker — receives data, writes to ring buffer via SharedArrayBuffer
79
- - [ ] Downsample worker — incremental pyramid update off main thread
80
- - [ ] Main thread — reads coherent snapshot, uploads visible range to GPU
81
- - [ ] `OffscreenCanvas` optional path
82
-
83
- Data structures have correctness coverage, but the incremental pyramid API must be finalized before moving them off main thread.
84
-
85
- ---
86
-
87
- ## Phase 3 — regl renderer (full)
88
-
89
- **Status: not started**
90
-
91
- - [x] `ReglBackend` — createBuffer, updateBuffer (subdata), createProgram, draw command cache
92
- - [ ] Persistent buffer pool (no Float32Array allocs per frame)
93
- - [x] Raw line strip for few visible points
94
- - [x] `MinMaxSegmentRenderer` — vertical min/max segments for dense viewports
95
- - [ ] Instanced draw for segment mode
96
- - [x] Camera transform as uniforms (scale/offset getters on Camera2D)
97
- - [ ] Two shader modes: `line.vert/frag` and `segment.vert/frag`
98
- - [x] `Renderer.drawMinMaxSegments`
99
- - [ ] Draw call batching per shader mode
100
-
101
- ---
102
-
103
- ## Phase 4 — Interaction
104
-
105
- **Status: implemented (camera + input)**
106
-
107
- - [x] `Camera2D` — viewport model with pan, zoom, setViewport
108
- - [x] `InputController` — pointer pan, wheel zoom, touch via Pointer Events
109
- - [x] `ViewportPolicy` — transforms pan/zoom intents and can update camera before render
110
- - [x] Preview synced-X policy — X stays live-followed while wheel zoom/pan affect Y only
111
- - [x] Camera uniforms propagated to shaders per frame
112
- - [ ] LOD re-query on pan/zoom (viewport change → new LODView)
113
- - [x] `AxisController` — smart tick generation and label formatting
114
- - [ ] Axis tick rendering (smart tick count, label formatting)
115
- - [x] Grid line rendering
116
-
117
- Camera modifies `Camera2D`, renderer reads it. No direct data access from interaction layer.
118
-
119
- ---
120
-
121
- ## Phase 5 — Multi-series
122
-
123
- **Status: data model ready**
124
-
125
- - [x] `Chart.addSeries()` supports multiple stores
126
- - [x] Each `SeriesStore` has independent buffer + pyramid + style
127
- - [ ] Batched draw calls (same shader → one draw per series group)
128
- - [ ] Shared X axis optional, independent Y per series
129
- - [x] Color/style per-series
130
- - [x] Series visibility toggle
131
-
132
- Limit: solid lines only, no markers, no antialias, no spline, no fill.
133
-
134
- ---
135
-
136
- ## Phase 6 — Public API
137
-
138
- **Status: basic shape exists**
139
-
140
- - [x] `new Chart(canvas)`
141
- - [x] `new Chart(canvas, { viewportPolicy })`
142
- - [x] `chart.addSeries(config, style)`
143
- - [x] `chart.setViewport({ xMin, xMax, yMin, yMax })`
144
- - [x] `chart.start()` / `chart.stop()`
145
- - [x] `chart.resize()` — handle container resize with DPR
146
- - [x] `series.append(x, y)` — accepts typed arrays
147
- - [x] `series.clear()`
148
- - [x] `chart.removeSeries(series)`
149
- - [ ] Axis labels / tick rendering
150
- - [x] Grid
151
- - [ ] Legend
152
- - [ ] Tooltip / hit testing
153
- - [ ] Export image
154
- - [ ] Theme system
155
- - [x] ResizeObserver integration
156
-
157
- Package status:
158
- - [x] `exports`, `main`, `module`, and `types` point at `dist/`
159
- - [x] Vite library build from `src/index.ts`
160
- - [x] Declaration emit from `src/` only via Vite d.ts plugin
161
- - [x] `bun pm pack --dry-run` includes package files only
162
-
163
- ---
164
-
165
- ## Downsampler — LOD engine
166
-
167
- **Status: basic pyramid built, not incremental**
168
-
169
- Current: `MinMaxPyramid.build()` does a full bottom-up rebuild. Target:
170
-
171
- ```
172
- raw level: x: Float64Array, y: Float32Array
173
- level 1: minY/maxY per bucket of 2
174
- level 2: minY/maxY per bucket of 4
175
- level 3: minY/maxY per bucket of 8
176
-
177
- ```
178
-
179
- **Incremental append**: each append updates only the chain of closed buckets. Query is O(buckets in viewport).
180
-
181
- Planned incremental design:
182
- - Raw samples are addressed by monotonically increasing logical sample index, not physical ring position.
183
- - Level `n` bucket width is `bucketSize ** (n + 1)` raw samples.
184
- - Appending a sample updates only level 0 while its bucket is open.
185
- - When a bucket closes, its min/max pair is propagated upward as one input sample for the next level.
186
- - Higher levels never read raw Y values; they combine child min/max pairs.
187
- - Ring wrap invalidates buckets whose covered logical index range was overwritten.
188
- - Query receives a visible logical index range from x-search and maps that range to bucket indices using the selected level width.
189
-
190
- **Query**: `samples_per_pixel = visible_samples / plotWidthPx`, pick `level = max(0, ceil(log2(samples_per_pixel)) - 1)`, return min/max pairs.
191
-
192
- **Render decision**:
193
- - few points → raw line strip
194
- - many points → vertical min/max segments
195
- - very many → envelope mesh
196
-
197
- ---
198
-
199
- ## Backend strategy
200
-
201
- ```
202
- V1: WebGL2 + regl ← CURRENT
203
- V2: Backend abstraction ← In place (GpuBackend interface)
204
- V3: WebGPU backend ← Future
205
- ```
206
-
207
- regl is the V1 backend, not the architecture. The `GpuBackend` interface decouples core from GPU.
208
-
209
- regl rules for V1:
210
- - Persistent buffers (no re-create per frame)
211
- - Precompiled regl commands
212
- - `subdata` on small ranges
213
- - Batched draw calls
214
- - Simple shaders, camera in uniforms
215
- - WebGL2 required (no fallback)
216
-
217
- ---
218
-
219
- ## Overflow semantics
220
-
221
- **Status: undecided**
222
-
223
- `RingBuffer` wraps silently at capacity. For streaming this is usually correct, but it should be explicit. Options:
224
- - Ring-buffer with wrap notification
225
- - Fixed capacity with error on overflow
226
- - Auto-growing buffer (breaks streaming contract)
227
-
228
- Deferred until we have a concrete use case.
229
-
230
- ---
231
-
232
- ## What we're NOT doing (V1)
233
-
234
- - SVG / Canvas2D fallback
235
- - Spline interpolation
236
- - Complex fill (gradient, area below)
237
- - Markers / point symbols
238
- - Antialias perfection
239
- - Recalculating axes in render loop
240
- - Per-series draw call without batching
241
-
242
- ---
243
-
244
- ## Competitive advantage
245
-
246
- Not WebGL. The core differentiator:
247
-
248
- > Incremental min/max pyramid + zero-allocation render loop + Camera2D viewport model
249
-
250
- Never render 10M points. Render `plotWidthPx * 2` (2k–8k vertices).
251
-
252
- ---
253
-
254
- ## Future / difficult
255
-
256
- - Multi-chart sync
257
- - Multiple Y axes
258
- - Spectrogram / heatmap
259
- - Large scatter ( > 1M points )
260
- - OHLC / candlestick
261
- - FFT / waterfall
262
- - Out-of-core data ( > RAM)
263
- - WebGPU backend