@photonviz/core 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -22,6 +22,42 @@ interface AxisConfig {
22
22
  minorTicks?: boolean | number;
23
23
  /** Axis title, drawn along the axis. */
24
24
  title?: string;
25
+ /** Draw the axis line. Default true. */
26
+ showAxisLine?: boolean;
27
+ /** Axis line color. Default: the per-axis `color`, else `theme.axis`. */
28
+ axisLineColor?: string;
29
+ /** Axis line width in px. Default 1. */
30
+ axisLineWidth?: number;
31
+ /** Draw tick marks. Default true. */
32
+ showTicks?: boolean;
33
+ /** Tick mark color. Default: the per-axis `color`, else `theme.axis`. */
34
+ tickColor?: string;
35
+ /** Major tick length in px. Default 5 (minor ticks are 3). */
36
+ tickLength?: number;
37
+ /** Tick mark line width in px. Default 1. */
38
+ tickWidth?: number;
39
+ /** Tick label color. Default: the per-axis `color`, else `theme.text`. */
40
+ labelColor?: string;
41
+ /** Tick label font (CSS `font` shorthand). Default `theme.font`. */
42
+ labelFont?: string;
43
+ /** Rotate tick labels by this many degrees. Default 0. */
44
+ labelRotation?: number;
45
+ /** Gap in px between a tick and its label. Default 3. */
46
+ labelStandoff?: number;
47
+ /** Axis title color. Default: the per-axis `color`, else `theme.text`. */
48
+ titleColor?: string;
49
+ /** Axis title font (CSS `font` shorthand). Default `theme.font`. */
50
+ titleFont?: string;
51
+ /** Draw grid lines for this axis. Default true. */
52
+ showGrid?: boolean;
53
+ /** Major grid line color. Default `theme.grid`. */
54
+ gridColor?: string;
55
+ /** Grid line width in px. Default 1. */
56
+ gridWidth?: number;
57
+ /** Grid line dash pattern (Canvas `setLineDash`). Default solid. */
58
+ gridDash?: number[];
59
+ /** Minor grid line color. Default `theme.gridMinor`. */
60
+ gridMinorColor?: string;
25
61
  }
26
62
  type Dim = "x" | "y";
27
63
  /**
@@ -32,6 +68,13 @@ type Dim = "x" | "y";
32
68
  * - `box-y` drag selects a y-range only (full width band) — Y-only zoom
33
69
  */
34
70
  type InteractionMode = "pan" | "box" | "box-x" | "box-y";
71
+ /**
72
+ * How a layer expects its data to change, mapped to a WebGL buffer-usage hint:
73
+ * `"static"` → `STATIC_DRAW` (upload once), `"dynamic"` → `DYNAMIC_DRAW` (stream
74
+ * via `setData`). Purely a performance hint — `setData` works either way. Default
75
+ * `"static"`. Set `"dynamic"` on layers you update every frame.
76
+ */
77
+ type RenderType = "static" | "dynamic";
35
78
  type Range = readonly [number, number];
36
79
  interface Bounds {
37
80
  x: Range;
@@ -95,6 +138,8 @@ interface AreaOptions {
95
138
  /** Lower edge(s). Number or per-point array — pass cumulative to stack. */
96
139
  base?: number | ArrayLike<number>;
97
140
  color?: string | Color;
141
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
142
+ renderType?: RenderType;
98
143
  name?: string;
99
144
  yAxis?: string;
100
145
  }
@@ -110,6 +155,7 @@ declare class AreaLayer implements Layer {
110
155
  private uniforms;
111
156
  private vertexCount;
112
157
  private color;
158
+ private usage;
113
159
  private xRef;
114
160
  private yRef;
115
161
  private xBounds;
@@ -136,7 +182,20 @@ interface BarOptions {
136
182
  width?: number;
137
183
  /** Shift bars by this many data units (use for grouped bars). */
138
184
  offset?: number;
185
+ /**
186
+ * `"v"` (default) draws vertical bars: `x` positions along the x axis, `y`
187
+ * values along the y axis. `"h"` draws horizontal bars: `x` positions along the
188
+ * **y** axis, `y` values along the **x** axis, `width` is the bar thickness.
189
+ */
190
+ orientation?: "v" | "h";
139
191
  color?: string | Color;
192
+ /**
193
+ * Per-bar colors (overrides {@link color}). Handy for tinting each bar — e.g.
194
+ * volume bars green/red by the candle's direction. Length should match `x`.
195
+ */
196
+ colors?: Array<string | Color>;
197
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
198
+ renderType?: RenderType;
140
199
  name?: string;
141
200
  yAxis?: string;
142
201
  }
@@ -152,16 +211,21 @@ declare class BarLayer implements Layer {
152
211
  private uniforms;
153
212
  private count;
154
213
  private color;
214
+ private colorsInput?;
215
+ private usage;
155
216
  private barWidth;
156
217
  private offset;
218
+ private orientation;
157
219
  private xRef;
158
220
  private yRef;
159
221
  private xBounds;
160
222
  private yBounds;
161
223
  constructor(gl: WebGL2RenderingContext, opts: BarOptions);
224
+ /** Per-bar color array (each bar uses its `colors[i]` or falls back to `color`). */
225
+ private buildColors;
162
226
  private buildRects;
163
- /** Replace bar values and re-upload (for streaming). */
164
- setData(x: ArrayLike<number>, y: ArrayLike<number>, base?: number | ArrayLike<number>): void;
227
+ /** Replace bar values (and optionally per-bar colors) and re-upload for streaming. */
228
+ setData(x: ArrayLike<number>, y: ArrayLike<number>, base?: number | ArrayLike<number>, colors?: Array<string | Color>): void;
165
229
  bounds(): {
166
230
  x: Range;
167
231
  y: Range;
@@ -185,6 +249,8 @@ interface BoxOptions {
185
249
  box?: boolean;
186
250
  /** Draw a violin (KDE) shape behind/instead of the box (default false). */
187
251
  violin?: boolean;
252
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
253
+ renderType?: RenderType;
188
254
  yAxis?: string;
189
255
  }
190
256
  declare class BoxLayer implements Layer {
@@ -204,7 +270,15 @@ declare class BoxLayer implements Layer {
204
270
  private lineCount;
205
271
  private pointStart;
206
272
  private pointCount;
273
+ private width;
274
+ private showBox;
275
+ private showViolin;
276
+ private usage;
207
277
  constructor(gl: WebGL2RenderingContext, opts: BoxOptions);
278
+ /** Build box/whisker/violin geometry from the groups; sets refs, bounds and draw ranges. */
279
+ private build;
280
+ /** Replace the box groups and rebuild the geometry (for streaming). */
281
+ setData(groups: BoxGroup[], width?: number): void;
208
282
  bounds(): {
209
283
  x: Range;
210
284
  y: Range;
@@ -228,9 +302,29 @@ interface CandlestickOptions {
228
302
  downColor?: string | Color;
229
303
  /** Wick thickness in CSS px. Default 1.5. */
230
304
  wickWidth?: number;
305
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
306
+ renderType?: RenderType;
231
307
  name?: string;
232
308
  yAxis?: string;
233
309
  }
310
+ /** The OHLC of a single candle — used by {@link CandlestickLayer.updateLast}/`appendCandle`. */
311
+ interface Candle {
312
+ x: number;
313
+ open: number;
314
+ high: number;
315
+ low: number;
316
+ close: number;
317
+ }
318
+ /** New OHLC arrays for {@link CandlestickLayer.setData} (colors/width stay fixed). */
319
+ interface CandlestickData {
320
+ x: ArrayLike<number>;
321
+ open: ArrayLike<number>;
322
+ high: ArrayLike<number>;
323
+ low: ArrayLike<number>;
324
+ close: ArrayLike<number>;
325
+ /** Optional new body width; keeps the previous width if omitted. */
326
+ width?: number;
327
+ }
234
328
  declare class CandlestickLayer implements Layer {
235
329
  readonly id: string;
236
330
  readonly name: string;
@@ -244,12 +338,120 @@ declare class CandlestickLayer implements Layer {
244
338
  private uBody;
245
339
  private uWick;
246
340
  private wickWidth;
341
+ private usage;
342
+ private up;
343
+ private down;
344
+ /** Body width in data units (median-derived unless the user fixed it). */
345
+ private bodyWidth;
346
+ private explicitWidth;
347
+ private xs;
348
+ private os;
349
+ private hs;
350
+ private ls;
351
+ private cs;
352
+ private rects;
353
+ private wicks;
354
+ private colors;
247
355
  private count;
248
356
  private xRef;
249
357
  private yRef;
250
358
  private xBounds;
251
359
  private yBounds;
252
360
  constructor(gl: WebGL2RenderingContext, opts: CandlestickOptions);
361
+ /** Copy the incoming OHLC arrays into the retained plain arrays. */
362
+ private ingest;
363
+ /** Write candle `i`'s body rect, wick segment and up/down color into the arrays. */
364
+ private emitCandle;
365
+ /** Recompute width/refs/bounds and refill the vertex arrays from the retained OHLC. */
366
+ private rebuild;
367
+ /** Re-upload all three per-candle buffers (after a full rebuild). */
368
+ private upload;
369
+ /** Replace every candle and re-upload (for streaming a whole new window). */
370
+ setData(data: CandlestickData): void;
371
+ /**
372
+ * Append one new candle (grows the series). Prefer {@link updateLast} for the
373
+ * in-progress candle and `appendCandle` only when a bar closes and a new one opens.
374
+ */
375
+ appendCandle(c: Candle): void;
376
+ /**
377
+ * Update the most recent candle in place — the cheap hot path for a live
378
+ * (forming) bar. Only that candle's 12 floats are re-uploaded; bounds are
379
+ * extended (never shrunk) to include it. No-op when the series is empty.
380
+ */
381
+ updateLast(c: Candle): void;
382
+ bounds(): {
383
+ x: Range;
384
+ y: Range;
385
+ } | null;
386
+ draw(state: DrawState): void;
387
+ dispose(): void;
388
+ }
389
+
390
+ /**
391
+ * An OHLC bar chart — the western cousin of the candlestick. Each period is a
392
+ * vertical low→high line with a left tick at the open and a right tick at the
393
+ * close, colored up/down by direction. Streams like {@link CandlestickLayer}.
394
+ */
395
+ interface OhlcOptions {
396
+ /** Bar positions (data space — e.g. epoch ms on a time axis). */
397
+ x: ArrayLike<number>;
398
+ open: ArrayLike<number>;
399
+ high: ArrayLike<number>;
400
+ low: ArrayLike<number>;
401
+ close: ArrayLike<number>;
402
+ /** Total tick span in data units (each open/close tick is half of this). Default 70% of median spacing. */
403
+ width?: number;
404
+ /** Close ≥ open color. Default green. */
405
+ upColor?: string | Color;
406
+ /** Close < open color. Default red. */
407
+ downColor?: string | Color;
408
+ /** Line thickness in CSS px. Default 1.5. */
409
+ lineWidth?: number;
410
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
411
+ renderType?: RenderType;
412
+ name?: string;
413
+ yAxis?: string;
414
+ }
415
+ declare class OhlcLayer implements Layer {
416
+ readonly id: string;
417
+ readonly name: string;
418
+ readonly colorCss: string;
419
+ readonly yAxis: string;
420
+ private gl;
421
+ private program;
422
+ private vao;
423
+ private buffers;
424
+ private uniforms;
425
+ private lineWidth;
426
+ private usage;
427
+ private up;
428
+ private down;
429
+ private barWidth;
430
+ private explicitWidth;
431
+ private xs;
432
+ private os;
433
+ private hs;
434
+ private ls;
435
+ private cs;
436
+ private segs;
437
+ private colors;
438
+ private count;
439
+ private xRef;
440
+ private yRef;
441
+ private xBounds;
442
+ private yBounds;
443
+ constructor(gl: WebGL2RenderingContext, opts: OhlcOptions);
444
+ private ingest;
445
+ /** Write bar `i`'s three segments (+ colors) at instance base `i * SEGS_PER_BAR`. */
446
+ private emitBar;
447
+ private rebuild;
448
+ private upload;
449
+ /** Replace every bar and re-upload (for streaming a whole new window). */
450
+ setData(data: CandlestickData): void;
451
+ /** Append one new bar (grows the series). */
452
+ appendCandle(c: Candle): void;
453
+ /** Update the most recent bar in place — the cheap hot path for a live bar. */
454
+ updateLast(c: Candle): void;
253
455
  bounds(): {
254
456
  x: Range;
255
457
  y: Range;
@@ -260,7 +462,13 @@ declare class CandlestickLayer implements Layer {
260
462
 
261
463
  type RGB = [number, number, number];
262
464
  type ColormapName = "viridis" | "plasma" | "coolwarm" | "grayscale";
263
- /** Returns a `(t in 0..1) => RGB` sampler for the named colormap. */
465
+ /**
466
+ * The raw `256×3` (r,g,b in 0..1) lookup table for a colormap, cached per name.
467
+ * Hot loops (heatmap, colorBy, …) can index it directly — `j = ((clamp(t)*255)|0)*3`
468
+ * — to avoid a per-element closure call and tuple allocation.
469
+ */
470
+ declare function colormapLUT(name?: ColormapName): Float32Array;
471
+ /** Returns a `(t in 0..1) => RGB` sampler for the named colormap (LUT-backed). */
264
472
  declare function colormap(name?: ColormapName): (t: number) => RGB;
265
473
 
266
474
  interface ContourOptions {
@@ -277,6 +485,8 @@ interface ContourOptions {
277
485
  /** Single line color; if omitted, levels are colored by a colormap. */
278
486
  color?: string | Color;
279
487
  colormap?: ColormapName;
488
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
489
+ renderType?: RenderType;
280
490
  yAxis?: string;
281
491
  }
282
492
  declare class ContourLayer implements Layer {
@@ -291,7 +501,17 @@ declare class ContourLayer implements Layer {
291
501
  private xRef;
292
502
  private yRef;
293
503
  private ext;
504
+ private cols;
505
+ private rows;
506
+ private levelsOpt;
507
+ private cmap;
508
+ private fixedColor;
509
+ private usage;
294
510
  constructor(gl: WebGL2RenderingContext, opts: ContourOptions);
511
+ /** Marching-squares the scalar field into iso-line segments; sets vertexCount. */
512
+ private build;
513
+ /** Replace the scalar field and recompute the iso lines (for streaming). */
514
+ setData(values: ArrayLike<number>, cols?: number, rows?: number): void;
295
515
  bounds(): {
296
516
  x: Range;
297
517
  y: Range;
@@ -323,9 +543,20 @@ interface ErrorBarOptions {
323
543
  band?: boolean;
324
544
  /** Band fill opacity. Default 0.2. */
325
545
  bandOpacity?: number;
546
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
547
+ renderType?: RenderType;
326
548
  name?: string;
327
549
  yAxis?: string;
328
550
  }
551
+ /** New positions/errors for {@link ErrorBarLayer.setData} (styling stays fixed). */
552
+ interface ErrorBarData {
553
+ x: ArrayLike<number>;
554
+ y: ArrayLike<number>;
555
+ yerr?: ErrInput;
556
+ yerrLow?: ErrInput;
557
+ yerrHigh?: ErrInput;
558
+ xerr?: ErrInput;
559
+ }
329
560
  declare class ErrorBarLayer implements Layer {
330
561
  readonly id: string;
331
562
  readonly name: string;
@@ -346,6 +577,7 @@ declare class ErrorBarLayer implements Layer {
346
577
  private bandOpacity;
347
578
  private showWhiskers;
348
579
  private showBand;
580
+ private usage;
349
581
  private segCount;
350
582
  private capCount;
351
583
  private bandVerts;
@@ -354,6 +586,73 @@ declare class ErrorBarLayer implements Layer {
354
586
  private xBounds;
355
587
  private yBounds;
356
588
  constructor(gl: WebGL2RenderingContext, opts: ErrorBarOptions);
589
+ /** Recompute refs/bounds/counts and the whisker/cap/band vertex arrays from new data. */
590
+ private build;
591
+ /** Replace the data and re-upload (for streaming). */
592
+ setData(data: ErrorBarData): void;
593
+ bounds(): {
594
+ x: Range;
595
+ y: Range;
596
+ } | null;
597
+ draw(state: DrawState): void;
598
+ dispose(): void;
599
+ }
600
+
601
+ interface GraphOptions {
602
+ /** Node positions (data space). */
603
+ x: ArrayLike<number>;
604
+ y: ArrayLike<number>;
605
+ /** Edges as index pairs into the node arrays. */
606
+ edges: ReadonlyArray<readonly [number, number]>;
607
+ nodeColor?: string | Color;
608
+ /** Node diameter in CSS pixels. Default 10. */
609
+ nodeSize?: number;
610
+ edgeColor?: string | Color;
611
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
612
+ renderType?: RenderType;
613
+ name?: string;
614
+ yAxis?: string;
615
+ }
616
+ /** New nodes/edges for {@link GraphLayer.setData} (colors/size stay fixed). */
617
+ interface GraphData {
618
+ /** Node positions. Omit both to run a force layout from `edges`. */
619
+ x?: ArrayLike<number>;
620
+ y?: ArrayLike<number>;
621
+ edges: ReadonlyArray<readonly [number, number]>;
622
+ /** Node count for the force layout when `x`/`y` are omitted. Defaults to max edge index + 1. */
623
+ nodeCount?: number;
624
+ }
625
+ /** A node-link graph: edges as line segments, nodes as round points. */
626
+ declare class GraphLayer implements Layer {
627
+ readonly id: string;
628
+ readonly name: string;
629
+ readonly colorCss: string;
630
+ readonly yAxis: string;
631
+ private gl;
632
+ private progs;
633
+ private nodeVao;
634
+ private edgeVao;
635
+ private buffers;
636
+ private edgeUniforms;
637
+ private nodeUniforms;
638
+ private nodeCount;
639
+ private edgeVerts;
640
+ private nodeColor;
641
+ private edgeColor;
642
+ private nodeSize;
643
+ private xRef;
644
+ private yRef;
645
+ private xBounds;
646
+ private yBounds;
647
+ private usage;
648
+ constructor(gl: WebGL2RenderingContext, opts: GraphOptions);
649
+ /** Build node/edge vertex arrays from positions + edges; sets counts, refs and bounds. */
650
+ private build;
651
+ /**
652
+ * Replace nodes and edges (for streaming). When `x`/`y` are omitted, node
653
+ * positions are recomputed with the package's force layout from the edges.
654
+ */
655
+ setData(data: GraphData): void;
357
656
  bounds(): {
358
657
  x: Range;
359
658
  y: Range;
@@ -377,6 +676,8 @@ interface HeatmapOptions {
377
676
  domain?: Range;
378
677
  /** Bilinear filtering (default true) vs. hard cells. */
379
678
  smooth?: boolean;
679
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
680
+ renderType?: RenderType;
380
681
  yAxis?: string;
381
682
  }
382
683
  declare class HeatmapLayer implements Layer {
@@ -391,7 +692,15 @@ declare class HeatmapLayer implements Layer {
391
692
  private xRef;
392
693
  private yRef;
393
694
  private ext;
695
+ private lut;
696
+ private fixedDomain;
697
+ private cols;
698
+ private rows;
394
699
  constructor(gl: WebGL2RenderingContext, opts: HeatmapOptions);
700
+ /** Bake a `cols*rows` value grid into the RGBA data texture via the colormap. */
701
+ private uploadValues;
702
+ /** Replace the value grid and re-bake the data texture (for streaming). */
703
+ setData(values: ArrayLike<number>, cols?: number, rows?: number): void;
395
704
  bounds(): {
396
705
  x: Range;
397
706
  y: Range;
@@ -408,6 +717,8 @@ interface HexbinOptions {
408
717
  colormap?: ColormapName;
409
718
  /** Count range mapped to the colormap. Defaults to [1, maxCount]. */
410
719
  domain?: Range;
720
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
721
+ renderType?: RenderType;
411
722
  yAxis?: string;
412
723
  }
413
724
  declare class HexbinLayer implements Layer {
@@ -424,7 +735,15 @@ declare class HexbinLayer implements Layer {
424
735
  private yRef;
425
736
  private xBounds;
426
737
  private yBounds;
738
+ private cmap;
739
+ private explicitRadius;
740
+ private domain;
741
+ private usage;
427
742
  constructor(gl: WebGL2RenderingContext, opts: HexbinOptions);
743
+ /** Bin the points into hex cells; sets radius, refs, bounds and cell count. */
744
+ private build;
745
+ /** Replace the point arrays, re-bin and re-upload the cells (for streaming). */
746
+ setData(x: ArrayLike<number>, y: ArrayLike<number>): void;
428
747
  bounds(): {
429
748
  x: Range;
430
749
  y: Range;
@@ -433,6 +752,65 @@ declare class HexbinLayer implements Layer {
433
752
  dispose(): void;
434
753
  }
435
754
 
755
+ /** Anything `texImage2D` accepts, or a URL string the layer loads itself. */
756
+ type ImageSource = TexImageSource | string;
757
+ interface ImageOptions {
758
+ /** A decoded bitmap/canvas/ImageData, or a URL to load (CORS-enabled). */
759
+ source: ImageSource;
760
+ /** Data-space rectangle the image spans. */
761
+ extent: {
762
+ x: Range;
763
+ y: Range;
764
+ };
765
+ /** Bilinear filtering (default) vs. nearest. */
766
+ smooth?: boolean;
767
+ /** Overall opacity 0..1. Default 1. */
768
+ opacity?: number;
769
+ /** Called after an async (URL) image finishes loading — wire to `plot.requestRender`. */
770
+ onLoad?: () => void;
771
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
772
+ renderType?: RenderType;
773
+ name?: string;
774
+ yAxis?: string;
775
+ }
776
+ /**
777
+ * An RGBA image (Bokeh `image_rgba` / `image_url`) drawn as a textured quad over
778
+ * a data-space extent — reuses the heatmap quad path. A `string` source is loaded
779
+ * asynchronously; pass `onLoad` (→ `plot.requestRender`) so the plot redraws once
780
+ * the pixels arrive.
781
+ */
782
+ declare class ImageLayer implements Layer {
783
+ readonly id: string;
784
+ readonly name: string;
785
+ readonly colorCss = "#94a3b8";
786
+ readonly yAxis: string;
787
+ private gl;
788
+ private program;
789
+ private vao;
790
+ private buffer;
791
+ private texture;
792
+ private uniforms;
793
+ private xRef;
794
+ private yRef;
795
+ private ext;
796
+ private opacity;
797
+ private smooth;
798
+ private ready;
799
+ private img;
800
+ constructor(gl: WebGL2RenderingContext, opts: ImageOptions);
801
+ /** Point the texture at a new source: load a URL async, or upload a bitmap now. */
802
+ private setSource;
803
+ /** Replace the image source and re-upload the texture (for streaming). */
804
+ setData(source: ImageSource, onLoad?: () => void): void;
805
+ private upload;
806
+ bounds(): {
807
+ x: Range;
808
+ y: Range;
809
+ };
810
+ draw(state: DrawState): void;
811
+ dispose(): void;
812
+ }
813
+
436
814
  /**
437
815
  * Shared hover-picking used by point/series layers (line, scatter, stem).
438
816
  *
@@ -483,6 +861,8 @@ interface LineOptions {
483
861
  * zoomed out (preserves peaks). Requires monotonic x; auto-detected. Default true.
484
862
  */
485
863
  decimate?: boolean;
864
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
865
+ renderType?: RenderType;
486
866
  }
487
867
  declare class LineLayer implements Layer {
488
868
  readonly id: string;
@@ -511,6 +891,7 @@ declare class LineLayer implements Layer {
511
891
  private monotonic;
512
892
  private gpuDec;
513
893
  private step?;
894
+ private usage;
514
895
  private xRef;
515
896
  private yRef;
516
897
  private xs;
@@ -540,6 +921,131 @@ declare class LineLayer implements Layer {
540
921
  dispose(): void;
541
922
  }
542
923
 
924
+ /** One filled polygon: a ring of `x`/`y`, with optional holes. */
925
+ interface Patch {
926
+ x: ArrayLike<number>;
927
+ y: ArrayLike<number>;
928
+ /** Vertex indices where each hole ring starts (mapbox-earcut convention). */
929
+ holes?: number[];
930
+ /** Explicit fill color (overrides the layer default / colormap). */
931
+ color?: string | Color;
932
+ /** Value used to color this patch via the layer `colormap` (choropleth). */
933
+ value?: number;
934
+ }
935
+ interface PatchesOptions {
936
+ patches: Patch[];
937
+ /** Default fill for patches without their own `color`/`value`. */
938
+ color?: string | Color;
939
+ /** Color patches by `value` through this colormap (choropleth). */
940
+ colormap?: ColormapName;
941
+ /** Value range mapped to [0,1] for the colormap. Defaults to the data min/max. */
942
+ domain?: Range;
943
+ /** Fill opacity, 0..1. Default 1. */
944
+ opacity?: number;
945
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
946
+ renderType?: RenderType;
947
+ name?: string;
948
+ yAxis?: string;
949
+ }
950
+ /**
951
+ * Filled polygons (Bokeh `patches`). Each ring is triangulated once on the CPU
952
+ * with ear-clipping (holes supported), then rendered as a static per-vertex-color
953
+ * triangle soup — only the transform uniforms change per frame.
954
+ */
955
+ declare class PatchesLayer implements Layer {
956
+ readonly id: string;
957
+ readonly name: string;
958
+ readonly colorCss: string;
959
+ readonly yAxis: string;
960
+ private gl;
961
+ private program;
962
+ private vao;
963
+ private buffers;
964
+ private uniforms;
965
+ private vertexCount;
966
+ private xRef;
967
+ private yRef;
968
+ private xBounds;
969
+ private yBounds;
970
+ private defRgba;
971
+ private opacity;
972
+ private cmap;
973
+ private domainOpt;
974
+ private usage;
975
+ constructor(gl: WebGL2RenderingContext, opts: PatchesOptions);
976
+ /** Triangulate the patches and recompute refs/bounds/vertexCount into position/color arrays. */
977
+ private build;
978
+ /** Replace the patches and re-upload (for streaming). */
979
+ setData(patches: Patch[]): void;
980
+ bounds(): {
981
+ x: Range;
982
+ y: Range;
983
+ } | null;
984
+ draw(state: DrawState): void;
985
+ dispose(): void;
986
+ }
987
+
988
+ interface PieOptions {
989
+ /** Slice magnitudes (need not sum to 1 — they are normalized). */
990
+ values: ArrayLike<number>;
991
+ /** Explicit per-slice colors; falls back to `colormap`, then a default palette. */
992
+ colors?: (string | Color)[];
993
+ /** Color slices by index through this colormap instead of the palette. */
994
+ colormap?: ColormapName;
995
+ /** Center in data space. Default `[0, 0]`. */
996
+ center?: [number, number];
997
+ /** Outer radius in data units. Default `1`. */
998
+ radius?: number;
999
+ /** Inner radius (> 0 makes a donut). Default `0`. */
1000
+ innerRadius?: number;
1001
+ /** Angle of the first slice edge, radians. Default `Math.PI / 2` (12 o'clock). */
1002
+ startAngle?: number;
1003
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1004
+ renderType?: RenderType;
1005
+ name?: string;
1006
+ yAxis?: string;
1007
+ }
1008
+ /**
1009
+ * A pie / donut chart drawn as a per-vertex-color triangle soup (wedges as fans,
1010
+ * or quad strips when a donut). Reuses the shared solid-fill program. Slices sweep
1011
+ * clockwise from `startAngle`. Set the plot's `equalAspect` so it stays circular.
1012
+ */
1013
+ declare class PieLayer implements Layer {
1014
+ readonly id: string;
1015
+ readonly name: string;
1016
+ readonly colorCss: string;
1017
+ readonly yAxis: string;
1018
+ private gl;
1019
+ private program;
1020
+ private vao;
1021
+ private buffers;
1022
+ private uniforms;
1023
+ private vertexCount;
1024
+ private xRef;
1025
+ private yRef;
1026
+ private xBounds;
1027
+ private yBounds;
1028
+ private cx;
1029
+ private cy;
1030
+ private R;
1031
+ private rIn;
1032
+ private start;
1033
+ private colorsOpt;
1034
+ private cmap;
1035
+ private usage;
1036
+ constructor(gl: WebGL2RenderingContext, opts: PieOptions);
1037
+ /** Recompute vertexCount and the position/color triangle soup from new slice values. */
1038
+ private build;
1039
+ /** Replace the slice values and re-upload (for streaming). */
1040
+ setData(values: ArrayLike<number>): void;
1041
+ bounds(): {
1042
+ x: Range;
1043
+ y: Range;
1044
+ } | null;
1045
+ draw(state: DrawState): void;
1046
+ dispose(): void;
1047
+ }
1048
+
543
1049
  interface QuiverOptions {
544
1050
  /** Arrow anchor positions (data space). */
545
1051
  x: ArrayLike<number>;
@@ -560,6 +1066,8 @@ interface QuiverOptions {
560
1066
  colormap?: ColormapName;
561
1067
  domain?: Range;
562
1068
  };
1069
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1070
+ renderType?: RenderType;
563
1071
  name?: string;
564
1072
  yAxis?: string;
565
1073
  }
@@ -579,6 +1087,9 @@ declare class QuiverLayer implements Layer {
579
1087
  private width;
580
1088
  private headSize;
581
1089
  private useVertexColor;
1090
+ private explicitScale;
1091
+ private colorBy;
1092
+ private usage;
582
1093
  private count;
583
1094
  private xRef;
584
1095
  private yRef;
@@ -586,6 +1097,10 @@ declare class QuiverLayer implements Layer {
586
1097
  private yBounds;
587
1098
  constructor(gl: WebGL2RenderingContext, opts: QuiverOptions);
588
1099
  private bindInstanceAttribs;
1100
+ /** Recompute count/refs/bounds and the arrow+color arrays from new x/y/u/v. */
1101
+ private build;
1102
+ /** Replace the data and re-upload (for streaming). */
1103
+ setData(x: ArrayLike<number>, y: ArrayLike<number>, u: ArrayLike<number>, v: ArrayLike<number>): void;
589
1104
  bounds(): {
590
1105
  x: Range;
591
1106
  y: Range;
@@ -594,12 +1109,16 @@ declare class QuiverLayer implements Layer {
594
1109
  dispose(): void;
595
1110
  }
596
1111
 
1112
+ /** Marker glyph shape for a scatter series. */
1113
+ type MarkerShape = "circle" | "square" | "triangle" | "diamond" | "cross" | "plus";
597
1114
  interface ScatterOptions {
598
1115
  x: ArrayLike<number>;
599
1116
  y: ArrayLike<number>;
600
1117
  color?: string | Color;
601
1118
  /** Marker diameter in CSS pixels. */
602
1119
  size?: number;
1120
+ /** Marker glyph. Default `"circle"`. */
1121
+ marker?: MarkerShape;
603
1122
  name?: string;
604
1123
  yAxis?: string;
605
1124
  /**
@@ -615,6 +1134,8 @@ interface ScatterOptions {
615
1134
  /** Value range mapped to [0,1]. Defaults to the data min/max. */
616
1135
  domain?: Range;
617
1136
  };
1137
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1138
+ renderType?: RenderType;
618
1139
  }
619
1140
  declare class ScatterLayer implements Layer {
620
1141
  readonly id: string;
@@ -628,6 +1149,8 @@ declare class ScatterLayer implements Layer {
628
1149
  private uniforms;
629
1150
  private count;
630
1151
  private size;
1152
+ private marker;
1153
+ private usage;
631
1154
  private color;
632
1155
  private useVertexColor;
633
1156
  private labels?;
@@ -661,6 +1184,8 @@ interface StemOptions {
661
1184
  width?: number;
662
1185
  /** Tip marker diameter in CSS px (0 hides). Default 6. */
663
1186
  markerSize?: number;
1187
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1188
+ renderType?: RenderType;
664
1189
  name?: string;
665
1190
  yAxis?: string;
666
1191
  }
@@ -680,6 +1205,7 @@ declare class StemLayer implements Layer {
680
1205
  private width;
681
1206
  private markerSize;
682
1207
  private count;
1208
+ private usage;
683
1209
  private baseline;
684
1210
  private xRef;
685
1211
  private yRef;
@@ -688,6 +1214,10 @@ declare class StemLayer implements Layer {
688
1214
  private xBounds;
689
1215
  private yBounds;
690
1216
  constructor(gl: WebGL2RenderingContext, opts: StemOptions);
1217
+ /** Recompute count/refs/bounds and the stem+tip vertex arrays from new x/y. */
1218
+ private build;
1219
+ /** Replace the data and re-upload (for streaming). */
1220
+ setData(x: ArrayLike<number>, y: ArrayLike<number>): void;
691
1221
  bounds(): {
692
1222
  x: Range;
693
1223
  y: Range;
@@ -748,8 +1278,50 @@ declare class TimeScale implements Scale {
748
1278
  ticks(target?: number): Tick[];
749
1279
  formatTick(value: number): string;
750
1280
  }
751
- type ScaleType = "linear" | "log" | "time";
752
- declare function makeScale(type: ScaleType, domain?: Range): Scale;
1281
+ /**
1282
+ * A categorical (factor) axis. Internally it is **linear over a band domain**
1283
+ * `[-0.5, n-0.5]`, so factor `i` sits at the band centre and `norm(i)` equals the
1284
+ * ordinary linear projection — the GPU transform needs no special handling, and a
1285
+ * layer plotting at integer indices lands on band centres automatically.
1286
+ * "Categorical-ness" lives only in the ticks/labels (one per factor).
1287
+ */
1288
+ declare class CategoricalScale implements Scale {
1289
+ readonly type = "categorical";
1290
+ readonly log = false;
1291
+ factors: string[];
1292
+ domain: Range;
1293
+ constructor(factors?: string[]);
1294
+ norm(value: number): number;
1295
+ invert(t: number): number;
1296
+ ticks(): Tick[];
1297
+ formatTick(value: number): string;
1298
+ }
1299
+ /**
1300
+ * An **ordinal time** axis — the standard financial x-axis. Bars are plotted at
1301
+ * evenly-spaced integer indices `0..n-1` (like {@link CategoricalScale}, so the
1302
+ * domain is the band `[-0.5, n-1+0.5]`), which **collapses market gaps**
1303
+ * (weekends, overnight, holidays) instead of leaving blank space the way a real
1304
+ * {@link TimeScale} would. Each index carries a timestamp; ticks are placed at
1305
+ * natural calendar boundaries (day / month / year, or hour / minute when zoomed
1306
+ * in) and subsampled toward the target count, so labels stay readable at any zoom.
1307
+ *
1308
+ * Plot your candles/bars at `x = 0,1,2,…` and pass the per-bar epoch-ms `times`.
1309
+ */
1310
+ declare class OrdinalTimeScale implements Scale {
1311
+ readonly type = "ordinal-time";
1312
+ readonly log = false;
1313
+ times: number[];
1314
+ domain: Range;
1315
+ constructor(times?: ArrayLike<number>);
1316
+ norm(value: number): number;
1317
+ invert(t: number): number;
1318
+ /** Timestamp at a (rounded, clamped) index. */
1319
+ private timeAt;
1320
+ ticks(target?: number): Tick[];
1321
+ formatTick(value: number): string;
1322
+ }
1323
+ type ScaleType = "linear" | "log" | "time" | "categorical" | "ordinal-time";
1324
+ declare function makeScale(type: ScaleType, domain?: Range, factors?: string[], times?: ArrayLike<number>): Scale;
753
1325
 
754
1326
  /** Pixel geometry of the plot, in CSS pixels. The plot region excludes margins. */
755
1327
  interface Layout {
@@ -771,52 +1343,206 @@ interface Theme {
771
1343
  }
772
1344
  declare const lightTheme: Theme;
773
1345
  declare const darkTheme: Theme;
1346
+ /** Concrete axis styling, resolved from an {@link AxisConfig} against a {@link Theme}. */
1347
+ interface ResolvedAxisStyle {
1348
+ showAxisLine: boolean;
1349
+ axisLineColor: string;
1350
+ axisLineWidth: number;
1351
+ showTicks: boolean;
1352
+ tickColor: string;
1353
+ tickLength: number;
1354
+ tickMinorLength: number;
1355
+ tickWidth: number;
1356
+ labelColor: string;
1357
+ labelFont: string;
1358
+ labelRotation: number;
1359
+ labelStandoff: number;
1360
+ titleColor: string;
1361
+ titleFont: string;
1362
+ showGrid: boolean;
1363
+ gridColor: string;
1364
+ gridMinorColor: string;
1365
+ gridWidth: number;
1366
+ gridDash: number[];
1367
+ }
1368
+ /**
1369
+ * Fold an {@link AxisConfig}'s optional style fields onto the theme defaults.
1370
+ * Colored fields fall back to `colorOverride` (a secondary y-axis's `color`) before
1371
+ * the theme, so an unstyled colored axis still tints its line/ticks/labels/title.
1372
+ * With an empty config this reproduces the pre-styling look exactly.
1373
+ */
1374
+ declare function resolveAxisStyle(cfg: AxisConfig, theme: Theme, colorOverride?: string): ResolvedAxisStyle;
1375
+ interface PlotTitleOptions {
1376
+ text: string;
1377
+ /** CSS `font` shorthand. Default `"600 15px system-ui, ..."`. */
1378
+ font?: string;
1379
+ color?: string;
1380
+ align?: "left" | "center" | "right";
1381
+ }
774
1382
 
775
1383
  interface AxisScaleOptions {
776
1384
  type?: ScaleType;
777
1385
  /** Fixed domain. If omitted, the axis autoscales to the data. */
778
1386
  domain?: Range;
1387
+ /** Factor labels for a `"categorical"` axis (fixes the domain to the bands). */
1388
+ factors?: string[];
1389
+ /**
1390
+ * Per-index epoch-ms timestamps for an `"ordinal-time"` axis (finance/session
1391
+ * axis). Plot bars at integer indices `0..times.length-1`; gaps collapse and
1392
+ * ticks show calendar dates.
1393
+ */
1394
+ times?: ArrayLike<number>;
1395
+ }
1396
+ /** Legend placement + styling. `legend: true` uses all defaults. */
1397
+ interface LegendOptions {
1398
+ /** Corner within the plot region. Default `"top-right"`. */
1399
+ position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
1400
+ /** Stack entries vertically (default) or in a row. */
1401
+ orientation?: "vertical" | "horizontal";
1402
+ background?: string;
1403
+ border?: string;
1404
+ textColor?: string;
1405
+ font?: string;
779
1406
  }
780
1407
  interface YAxisOptions extends AxisConfig {
781
1408
  type?: ScaleType;
782
1409
  domain?: Range;
1410
+ /** Factor labels for a `"categorical"` axis. */
1411
+ factors?: string[];
1412
+ /** Per-index epoch-ms timestamps for an `"ordinal-time"` axis. */
1413
+ times?: ArrayLike<number>;
783
1414
  /** Which side to draw the axis on. Default `"right"` for secondary axes. */
784
1415
  side?: "left" | "right";
785
1416
  /** Axis + label color (secondary axes often match their series). */
786
1417
  color?: string;
787
1418
  }
788
- /** One line of the hover tooltip header, produced by {@link PlotOptions.hoverReadout}. */
789
- interface HoverReadoutRow {
790
- label: string;
791
- value: string;
1419
+ /** One series in a grouped/stacked bar chart. */
1420
+ interface BarSeries {
1421
+ /** Value per category (parallel to the shared `x` positions). */
1422
+ y: ArrayLike<number>;
1423
+ color?: string;
1424
+ name?: string;
792
1425
  }
793
- interface PlotOptions {
794
- scales?: {
795
- x?: AxisScaleOptions;
796
- y?: AxisScaleOptions;
797
- };
798
- axes?: {
799
- x?: AxisConfig;
800
- y?: AxisConfig;
801
- };
802
- theme?: "light" | "dark" | Theme;
803
- margin?: Partial<Layout["margin"]>;
804
- /** Enable wheel-zoom and drag interaction. Default true. */
805
- interactive?: boolean;
806
- /** Show the built-in toolbar (home + pan/box/X/Y zoom modes). Default true. */
807
- showToolbar?: boolean;
808
- /** Initial interaction mode. Default `"pan"`. */
809
- mode?: InteractionMode;
810
- /** Enable hover crosshair + tooltip. Default true. */
811
- hover?: boolean;
812
- /**
813
- * How hover selects the highlighted point: `"x"` nearest by x (classic),
814
- * `"y"` nearest by y, or `"xy"` nearest by 2D distance — the last checks both
815
- * axes, which is what a scatter/map needs. Default `"x"`.
816
- */
817
- pick?: PickMode;
818
- /**
819
- * When a point's pinned detail box appears: `"click"` pins it on click (until
1426
+ /** Options for {@link Plot.addGroupedBars} — one cluster of bars per category. */
1427
+ interface GroupedBarOptions {
1428
+ /** Category positions (e.g. `0..n-1` for a categorical axis). */
1429
+ x: ArrayLike<number>;
1430
+ series: BarSeries[];
1431
+ /** Total width of one group (all its bars) in data units. Default 0.8. */
1432
+ groupWidth?: number;
1433
+ /** Fractional gap between bars within a group, 0..1. Default 0.1. */
1434
+ gap?: number;
1435
+ /** `"v"` vertical (default) or `"h"` horizontal bars. */
1436
+ orientation?: "v" | "h";
1437
+ yAxis?: string;
1438
+ }
1439
+ /** Options for {@link Plot.addStackedBars} series stacked on top of each other. */
1440
+ interface StackedBarOptions {
1441
+ /** Category positions (e.g. `0..n-1` for a categorical axis). */
1442
+ x: ArrayLike<number>;
1443
+ series: BarSeries[];
1444
+ /** Bar width in data units. Defaults to 80% of the median spacing. */
1445
+ width?: number;
1446
+ /** `"v"` vertical (default) or `"h"` horizontal bars. */
1447
+ orientation?: "v" | "h";
1448
+ yAxis?: string;
1449
+ }
1450
+ /** One series in a stacked area chart. */
1451
+ interface AreaSeries {
1452
+ y: ArrayLike<number>;
1453
+ color?: string;
1454
+ name?: string;
1455
+ }
1456
+ /** Options for {@link Plot.addStackedArea}. */
1457
+ interface StackedAreaOptions {
1458
+ x: ArrayLike<number>;
1459
+ series: AreaSeries[];
1460
+ yAxis?: string;
1461
+ }
1462
+ /** Options for {@link Plot.addGraph}. Positions are optional — omit them (give `nodes`) to auto-lay-out. */
1463
+ interface GraphInput extends Omit<GraphOptions, "x" | "y"> {
1464
+ x?: ArrayLike<number>;
1465
+ y?: ArrayLike<number>;
1466
+ /** Node count when `x`/`y` are omitted (else inferred from the max edge index). */
1467
+ nodes?: number;
1468
+ }
1469
+ /**
1470
+ * A Canvas2D overlay marker drawn above the data, projected through the scales:
1471
+ * a full-width/height guide line (`span`), a shaded range (`band`), a rectangle
1472
+ * (`box`), or text (`label`). `yAxis` targets a secondary axis where relevant.
1473
+ */
1474
+ type Annotation = {
1475
+ type: "span";
1476
+ dim: Dim;
1477
+ value: number;
1478
+ color?: string;
1479
+ width?: number;
1480
+ dash?: number[];
1481
+ yAxis?: string;
1482
+ } | {
1483
+ type: "band";
1484
+ dim: Dim;
1485
+ from: number;
1486
+ to: number;
1487
+ color?: string;
1488
+ yAxis?: string;
1489
+ } | {
1490
+ type: "box";
1491
+ x: Range;
1492
+ y: Range;
1493
+ color?: string;
1494
+ border?: string;
1495
+ yAxis?: string;
1496
+ } | {
1497
+ type: "label";
1498
+ x: number;
1499
+ y: number;
1500
+ text: string;
1501
+ color?: string;
1502
+ font?: string;
1503
+ align?: "left" | "center" | "right";
1504
+ yAxis?: string;
1505
+ };
1506
+ /** One line of the hover tooltip header, produced by {@link PlotOptions.hoverReadout}. */
1507
+ interface HoverReadoutRow {
1508
+ label: string;
1509
+ value: string;
1510
+ }
1511
+ interface PlotOptions {
1512
+ scales?: {
1513
+ x?: AxisScaleOptions;
1514
+ y?: AxisScaleOptions;
1515
+ };
1516
+ axes?: {
1517
+ x?: AxisConfig;
1518
+ y?: AxisConfig;
1519
+ };
1520
+ theme?: "light" | "dark" | Theme;
1521
+ /** Fill color for the plot region (inside the margins). Default transparent. */
1522
+ background?: string;
1523
+ /** Fill color for the whole canvas incl. margins. Default transparent. */
1524
+ border?: string;
1525
+ /** Plot title, drawn in a reserved strip above the plot. */
1526
+ title?: string | PlotTitleOptions;
1527
+ /** Show a legend of named series. `true` uses defaults; pass an object to place/style it. */
1528
+ legend?: boolean | LegendOptions;
1529
+ margin?: Partial<Layout["margin"]>;
1530
+ /** Enable wheel-zoom and drag interaction. Default true. */
1531
+ interactive?: boolean;
1532
+ /** Show the built-in toolbar (home + pan/box/X/Y zoom modes). Default true. */
1533
+ showToolbar?: boolean;
1534
+ /** Initial interaction mode. Default `"pan"`. */
1535
+ mode?: InteractionMode;
1536
+ /** Enable hover crosshair + tooltip. Default true. */
1537
+ hover?: boolean;
1538
+ /**
1539
+ * How hover selects the highlighted point: `"x"` nearest by x (classic),
1540
+ * `"y"` nearest by y, or `"xy"` nearest by 2D distance — the last checks both
1541
+ * axes, which is what a scatter/map needs. Default `"x"`.
1542
+ */
1543
+ pick?: PickMode;
1544
+ /**
1545
+ * When a point's pinned detail box appears: `"click"` pins it on click (until
820
1546
  * you click empty space), `"hover"` shows it while the cursor is over a point.
821
1547
  * Default `"click"`.
822
1548
  */
@@ -888,10 +1614,21 @@ declare class Plot {
888
1614
  private hoverReadout?;
889
1615
  /** Cursor position while the pointer is pressed, when `crosshair`. */
890
1616
  private pressPx;
1617
+ private viewListeners;
1618
+ private cursorListeners;
1619
+ private lastEmittedX;
1620
+ private lastEmittedCursor;
1621
+ private linkedCursorX;
891
1622
  private tooltip;
892
1623
  /** A point clicked to pin its details, until another click clears it. */
893
1624
  private selected;
894
1625
  private infoBox;
1626
+ private annotations;
1627
+ private bgFill?;
1628
+ private borderFill?;
1629
+ private title;
1630
+ private legend;
1631
+ private legendDiv;
895
1632
  constructor(container: HTMLElement, options?: PlotOptions);
896
1633
  private makeCanvas;
897
1634
  /** Margins grow to make room for extra y axes on each side. */
@@ -919,6 +1656,16 @@ declare class Plot {
919
1656
  addLine(opts: LineOptions): LineLayer;
920
1657
  addScatter(opts: ScatterOptions): ScatterLayer;
921
1658
  addBar(opts: BarOptions): BarLayer;
1659
+ /**
1660
+ * Grouped (clustered) bars: one {@link BarLayer} per series, each shifted within
1661
+ * its category group so the bars sit side by side. Returns the layers in order.
1662
+ */
1663
+ addGroupedBars(opts: GroupedBarOptions): BarLayer[];
1664
+ /**
1665
+ * Stacked bars: each series is drawn from the running cumulative total of the
1666
+ * ones before it, so they stack. Returns the layers bottom-to-top.
1667
+ */
1668
+ addStackedBars(opts: StackedBarOptions): BarLayer[];
922
1669
  addArea(opts: AreaOptions): AreaLayer;
923
1670
  addHeatmap(opts: HeatmapOptions): HeatmapLayer;
924
1671
  addBox(opts: BoxOptions): BoxLayer;
@@ -928,6 +1675,31 @@ declare class Plot {
928
1675
  addStem(opts: StemOptions): StemLayer;
929
1676
  addQuiver(opts: QuiverOptions): QuiverLayer;
930
1677
  addCandlestick(opts: CandlestickOptions): CandlestickLayer;
1678
+ /** An OHLC bar chart (low→high line with open/close ticks). Streams like candlesticks. */
1679
+ addOhlc(opts: OhlcOptions): OhlcLayer;
1680
+ /** Filled polygons (choropleth-capable). Rings are triangulated with earcut. */
1681
+ addPatches(opts: PatchesOptions): PatchesLayer;
1682
+ /** A pie / donut chart. Set `equalAspect: true` on the plot so it stays circular. */
1683
+ addPie(opts: PieOptions): PieLayer;
1684
+ /** An RGBA image / URL drawn over a data-space extent. URLs redraw on load. */
1685
+ addImage(opts: ImageOptions): ImageLayer;
1686
+ /**
1687
+ * A node-link graph. Provide node `x`/`y`, or omit them (with `nodes`, or let the
1688
+ * count be inferred from the edges) to auto-place with a force-directed layout.
1689
+ */
1690
+ addGraph(opts: GraphInput): GraphLayer;
1691
+ /**
1692
+ * Stacked area: each series is filled from the running cumulative total of the
1693
+ * ones before it. Returns the layers bottom-to-top.
1694
+ */
1695
+ addStackedArea(opts: StackedAreaOptions): AreaLayer[];
1696
+ /**
1697
+ * Add a Canvas2D annotation (span / band / box / label) drawn above the data.
1698
+ * Returns a disposer that removes just this annotation.
1699
+ */
1700
+ addAnnotation(a: Annotation): () => void;
1701
+ /** Remove all annotations. */
1702
+ clearAnnotations(): void;
931
1703
  /** Compute an STFT of `signal` and render it as a heatmap (time × frequency). */
932
1704
  addHeatmapSpectrogram(signal: ArrayLike<number>, opts?: {
933
1705
  fftSize?: number;
@@ -945,6 +1717,10 @@ declare class Plot {
945
1717
  }): BarLayer;
946
1718
  /** Register an additional named y axis. Series opt in via `addLine({ yAxis })`. */
947
1719
  addYAxis(id: string, opts?: YAxisOptions): void;
1720
+ /** Whether a y axis with this id exists (the primary is always `"y"`). */
1721
+ hasYAxis(id: string): boolean;
1722
+ /** Remove a secondary y axis. No-op for the primary `"y"` or an unknown id. */
1723
+ removeYAxis(id: string): void;
948
1724
  removeLayer(layer: Layer): void;
949
1725
  /** Configure ticks/format/title for the x axis or a y axis (default primary "y"). */
950
1726
  setAxis(dim: Dim | string, config: Partial<AxisConfig>): void;
@@ -954,6 +1730,18 @@ declare class Plot {
954
1730
  y?: Range;
955
1731
  yAxes?: Record<string, Range>;
956
1732
  }): void;
1733
+ /**
1734
+ * Subscribe to x-domain changes (pan / zoom / home / setView). Fires once per
1735
+ * frame after the domain settles. Returns an unsubscribe function. See {@link linkX}.
1736
+ */
1737
+ onViewChange(cb: (x: Range) => void): () => void;
1738
+ /**
1739
+ * Subscribe to the hover cursor's data-space x (or `null` when it leaves the
1740
+ * plot). Returns an unsubscribe function. Used to share a crosshair across panes.
1741
+ */
1742
+ onCursorMove(cb: (dataX: number | null) => void): () => void;
1743
+ /** Draw a linked crosshair at this data-space x (pushed from another pane), or clear it with `null`. */
1744
+ setLinkedCursor(dataX: number | null): void;
957
1745
  private setYDomain;
958
1746
  setMode(mode: InteractionMode): void;
959
1747
  getMode(): InteractionMode;
@@ -966,7 +1754,15 @@ declare class Plot {
966
1754
  private resize;
967
1755
  requestRender(): void;
968
1756
  private primaryY;
1757
+ /** Fire view/cursor listeners once the frame's x-domain + cursor are settled. */
1758
+ private emitLinks;
969
1759
  render(): void;
1760
+ /** Named series that can appear in the legend: any layer exposing name + colorCss. */
1761
+ private legendEntries;
1762
+ /** Rebuild and position the legend overlay (or hide it). */
1763
+ private updateLegend;
1764
+ /** Draw all annotations, projected through the scales and clipped to the region. */
1765
+ private renderAnnotations;
970
1766
  private renderHover;
971
1767
  private updateTooltip;
972
1768
  private updateCursor;
@@ -1006,6 +1802,21 @@ declare class Plot {
1006
1802
  private zoomAround;
1007
1803
  }
1008
1804
 
1805
+ /**
1806
+ * Link the x-axis (pan / zoom) and hover crosshair of several plots so they move
1807
+ * together — the standard multi-pane financial layout (price on top, volume /
1808
+ * RSI / MACD below, all sharing one time axis). The plots should share the same
1809
+ * x-scale semantics (e.g. all `ordinal-time` over the same bars).
1810
+ *
1811
+ * ```ts
1812
+ * const detach = linkX([pricePlot, volumePlot, rsiPlot]);
1813
+ * // …later: detach();
1814
+ * ```
1815
+ *
1816
+ * @returns a function that unlinks them again.
1817
+ */
1818
+ declare function linkX(plots: Plot[]): () => void;
1819
+
1009
1820
  /** The subset of Plot the toolbar drives. Kept minimal to avoid an import cycle. */
1010
1821
  interface ToolbarHost {
1011
1822
  setMode(mode: InteractionMode): void;
@@ -1027,6 +1838,25 @@ declare function createToolbar(container: HTMLElement, host: ToolbarHost, dark:
1027
1838
  destroy: () => void;
1028
1839
  };
1029
1840
 
1841
+ /**
1842
+ * A tiny deterministic force-directed layout (Fruchterman–Reingold style). Nodes
1843
+ * seed on a unit circle (no RNG — pure and unit-testable), then relax under
1844
+ * all-pairs repulsion + per-edge attraction + a gentle pull to the center, with
1845
+ * temperature cooling. Returns node positions in roughly a unit box around 0.
1846
+ */
1847
+ interface ForceLayoutOptions {
1848
+ /** Relaxation steps. Default 300. */
1849
+ iterations?: number;
1850
+ /** Layout area; the ideal edge length is `sqrt(area / n)`. Default 1. */
1851
+ area?: number;
1852
+ /** Pull toward the origin each step. Default 0.05. */
1853
+ gravity?: number;
1854
+ }
1855
+ declare function forceLayout(nodeCount: number, edges: ReadonlyArray<readonly [number, number]>, opts?: ForceLayoutOptions): {
1856
+ x: Float64Array;
1857
+ y: Float64Array;
1858
+ };
1859
+
1030
1860
  interface PolarOptions {
1031
1861
  theme?: "light" | "dark" | Theme;
1032
1862
  /** Angle unit of input theta values. Default `"rad"`. */
@@ -1054,6 +1884,8 @@ interface PolarLineOptions {
1054
1884
  width?: number;
1055
1885
  /** Connect the last point back to the first. */
1056
1886
  closed?: boolean;
1887
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1888
+ renderType?: RenderType;
1057
1889
  }
1058
1890
  interface PolarScatterOptions {
1059
1891
  theta: ArrayLike<number>;
@@ -1062,6 +1894,8 @@ interface PolarScatterOptions {
1062
1894
  size?: number;
1063
1895
  /** Optional per-point labels (one per point), shown as the title of the click-pinned info box. */
1064
1896
  labels?: ArrayLike<string>;
1897
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1898
+ renderType?: RenderType;
1065
1899
  }
1066
1900
  /** A live handle to update a polar series with new (theta, r) data. */
1067
1901
  interface PolarSeries {
@@ -1148,10 +1982,232 @@ interface Bounds3 {
1148
1982
  y: Range;
1149
1983
  z: Range;
1150
1984
  }
1985
+ /** A colormapped layer's scale, surfaced to {@link Plot3D} for a colorbar. */
1986
+ interface ColorInfo {
1987
+ colormap: ColormapName;
1988
+ domain: Range;
1989
+ label?: string;
1990
+ }
1151
1991
  /** A drawable in the 3D scene. Positions are in world space; Plot3D supplies the MVP. */
1152
1992
  interface Layer3D {
1153
1993
  readonly id: string;
1994
+ /** Series name for the legend (optional). */
1995
+ readonly name?: string;
1996
+ /** A solid CSS color for the legend swatch (solid-colored layers only). */
1997
+ readonly colorCss?: string;
1998
+ bounds3(): Bounds3 | null;
1999
+ /** Colormap + value range for a colorbar, if this layer is colormapped. */
2000
+ colorInfo?(): ColorInfo | null;
2001
+ /**
2002
+ * Data-space points for hover picking (xyz triples), with an optional per-point
2003
+ * tooltip label builder. Null if the layer isn't pickable.
2004
+ */
2005
+ pickData?(): {
2006
+ positions: Float32Array;
2007
+ label?: (i: number) => string;
2008
+ } | null;
2009
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
2010
+ dispose(): void;
2011
+ }
2012
+
2013
+ interface Bar3DOptions {
2014
+ /** Grid x positions (world). */
2015
+ x: ArrayLike<number>;
2016
+ /** Grid z positions (world). */
2017
+ z: ArrayLike<number>;
2018
+ /** Bar heights. */
2019
+ y: ArrayLike<number>;
2020
+ /** Footprint (world units). Defaults to ~0.7× the median grid spacing. */
2021
+ width?: number;
2022
+ color?: string | Color;
2023
+ /** Color bars via a colormap (over `values`, default the heights). */
2024
+ colorBy?: {
2025
+ values?: ArrayLike<number>;
2026
+ colormap?: ColormapName;
2027
+ domain?: Range;
2028
+ };
2029
+ name?: string;
2030
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2031
+ renderType?: RenderType;
2032
+ }
2033
+ /** 3D bars (columns) on an x/z grid, lit like the surface and optionally colormapped. */
2034
+ declare class Bar3DLayer implements Layer3D {
2035
+ readonly id: string;
2036
+ readonly name?: string;
2037
+ readonly colorCss?: string;
2038
+ private gl;
2039
+ private program;
2040
+ private vao;
2041
+ private buffers;
2042
+ private instBuf;
2043
+ private uniforms;
2044
+ private count;
2045
+ private width;
2046
+ private b3;
2047
+ private cInfo;
2048
+ private positions;
2049
+ private base;
2050
+ private optWidth?;
2051
+ private colorByOpt?;
2052
+ private usage;
2053
+ private lightDir;
2054
+ private ambient;
2055
+ constructor(gl: WebGL2RenderingContext, opts: Bar3DOptions);
2056
+ /** Build the per-bar instances (base/height/color) and (re)upload the instance buffer. */
2057
+ private build;
2058
+ /** Stream new bar positions/heights (instances rebuilt). Call `plot.refresh()` after. */
2059
+ setData(x: ArrayLike<number>, z: ArrayLike<number>, y: ArrayLike<number>): void;
2060
+ bounds3(): Bounds3 | null;
2061
+ colorInfo(): ColorInfo | null;
2062
+ pickData(): {
2063
+ positions: Float32Array<ArrayBufferLike>;
2064
+ } | null;
2065
+ /** Set the light direction (world space) and ambient term (0..1). */
2066
+ setLight(dir: [number, number, number], ambient: number): void;
2067
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
2068
+ dispose(): void;
2069
+ }
2070
+
2071
+ interface Contour3DOptions {
2072
+ /** Row-major height grid, length `cols * rows`. */
2073
+ values: ArrayLike<number>;
2074
+ cols: number;
2075
+ rows: number;
2076
+ /** World footprint. Defaults to unit indices. */
2077
+ extentX?: Range;
2078
+ extentZ?: Range;
2079
+ /** Iso levels: an explicit list, or a count of evenly-spaced levels. Default 10. */
2080
+ levels?: number[] | number;
2081
+ /** Single line color; if omitted, levels are colored by a colormap. */
2082
+ color?: string | Color;
2083
+ colormap?: ColormapName;
2084
+ name?: string;
2085
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2086
+ renderType?: RenderType;
2087
+ }
2088
+ /**
2089
+ * 3D contour: iso-height lines of a grid, each drawn at its own level height
2090
+ * (`y = level`) so they stack into a floating topographic map. Marching squares
2091
+ * on the CPU, per-vertex colored by level.
2092
+ */
2093
+ declare class Contour3DLayer implements Layer3D {
2094
+ readonly id: string;
2095
+ readonly name?: string;
2096
+ private gl;
2097
+ private program;
2098
+ private vao;
2099
+ private buffer;
2100
+ private uniforms;
2101
+ private vertCount;
2102
+ private b3;
2103
+ private cInfo;
2104
+ private cmapName;
2105
+ private fixed;
2106
+ private levelsOpt?;
2107
+ private cols;
2108
+ private rows;
2109
+ private extentX;
2110
+ private extentZ;
2111
+ private usage;
2112
+ constructor(gl: WebGL2RenderingContext, opts: Contour3DOptions);
2113
+ /** Marching-squares the grid at each iso level and (re)upload the line buffer. */
2114
+ private build;
2115
+ /** Stream a new scalar field (contours recomputed). Call `plot.refresh()` after. */
2116
+ setData(values: ArrayLike<number>, opts?: {
2117
+ cols?: number;
2118
+ rows?: number;
2119
+ extentX?: Range;
2120
+ extentZ?: Range;
2121
+ }): void;
2122
+ bounds3(): Bounds3 | null;
2123
+ colorInfo(): ColorInfo | null;
2124
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
2125
+ dispose(): void;
2126
+ }
2127
+
2128
+ interface IsosurfaceOptions {
2129
+ /** Scalar volume, length `nx*ny*nz`, indexed `x + y*nx + z*nx*ny`. */
2130
+ values: ArrayLike<number>;
2131
+ dims: [number, number, number];
2132
+ /** The iso value to extract the surface at. */
2133
+ isoLevel: number;
2134
+ /** World extent of the volume. Defaults to unit indices. */
2135
+ extent?: {
2136
+ x: Range;
2137
+ y: Range;
2138
+ z: Range;
2139
+ };
2140
+ color?: string | Color;
2141
+ /** Fill opacity 0..1. Default 1. */
2142
+ opacity?: number;
2143
+ name?: string;
2144
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2145
+ renderType?: RenderType;
2146
+ }
2147
+ /** A marching-cubes isosurface of a 3D scalar volume, lit and solid-colored. */
2148
+ declare class IsosurfaceLayer implements Layer3D {
2149
+ readonly id: string;
2150
+ readonly name?: string;
2151
+ readonly colorCss: string;
2152
+ private gl;
2153
+ private program;
2154
+ private vao;
2155
+ private buffer;
2156
+ private uniforms;
2157
+ private vertCount;
2158
+ private color;
2159
+ private opacity;
2160
+ private b3;
2161
+ private usage;
2162
+ private lightDir;
2163
+ private ambient;
2164
+ constructor(gl: WebGL2RenderingContext, opts: IsosurfaceOptions);
2165
+ /** Run marching cubes and (re)upload the interleaved pos/normal vertex buffer. */
2166
+ private build;
2167
+ /** Stream a new volume + iso level (marching-cubes mesh recomputed). Call `plot.refresh()` after. */
2168
+ setData(values: ArrayLike<number>, dims: [number, number, number], isoLevel: number, extent?: {
2169
+ x: Range;
2170
+ y: Range;
2171
+ z: Range;
2172
+ }): void;
2173
+ bounds3(): Bounds3 | null;
2174
+ /** Set the light direction (world space) and ambient term (0..1). */
2175
+ setLight(dir: [number, number, number], ambient: number): void;
2176
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
2177
+ dispose(): void;
2178
+ }
2179
+
2180
+ interface Line3DOptions {
2181
+ x: ArrayLike<number>;
2182
+ y: ArrayLike<number>;
2183
+ z: ArrayLike<number>;
2184
+ color?: string | Color;
2185
+ name?: string;
2186
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2187
+ renderType?: RenderType;
2188
+ }
2189
+ /** A 3D polyline / path (`GL_LINE_STRIP`). */
2190
+ declare class Line3DLayer implements Layer3D {
2191
+ readonly id: string;
2192
+ readonly name?: string;
2193
+ readonly colorCss: string;
2194
+ private gl;
2195
+ private program;
2196
+ private vao;
2197
+ private buffer;
2198
+ private uniforms;
2199
+ private count;
2200
+ private color;
2201
+ private b3;
2202
+ private positions;
2203
+ private usage;
2204
+ constructor(gl: WebGL2RenderingContext, opts: Line3DOptions);
1154
2205
  bounds3(): Bounds3 | null;
2206
+ pickData(): {
2207
+ positions: Float32Array<ArrayBufferLike>;
2208
+ } | null;
2209
+ /** Stream a new path. Call `plot.refresh()` afterwards to re-fit + redraw. */
2210
+ setData(x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number>): void;
1155
2211
  draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1156
2212
  dispose(): void;
1157
2213
  }
@@ -1161,15 +2217,26 @@ interface PointCloudOptions {
1161
2217
  y: ArrayLike<number>;
1162
2218
  z: ArrayLike<number>;
1163
2219
  color?: string | Color;
2220
+ /** Uniform point diameter (px) when `sizes` is omitted. Default 4. */
1164
2221
  size?: number;
2222
+ /** Per-point diameter (px); overrides `size` where > 0. */
2223
+ sizes?: ArrayLike<number>;
1165
2224
  colorBy?: {
1166
2225
  values: ArrayLike<number>;
1167
2226
  colormap?: ColormapName;
1168
2227
  domain?: Range;
1169
2228
  };
2229
+ /** Per-point tooltip text (parallel to x/y/z). */
2230
+ labels?: ArrayLike<string>;
2231
+ /** Series name (legend / colorbar label). */
2232
+ name?: string;
2233
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2234
+ renderType?: RenderType;
1170
2235
  }
1171
2236
  declare class PointCloudLayer implements Layer3D {
1172
2237
  readonly id: string;
2238
+ readonly name?: string;
2239
+ readonly colorCss?: string;
1173
2240
  private gl;
1174
2241
  private program;
1175
2242
  private vao;
@@ -1178,8 +2245,78 @@ declare class PointCloudLayer implements Layer3D {
1178
2245
  private count;
1179
2246
  private size;
1180
2247
  private b3;
2248
+ private cInfo;
2249
+ private positions;
2250
+ private labels?;
2251
+ /** Interleaved pos(3)+color(3)+size(1); positions are streamed in place. */
2252
+ private data;
2253
+ private usage;
1181
2254
  constructor(gl: WebGL2RenderingContext, opts: PointCloudOptions);
2255
+ private updateBounds;
2256
+ /** Stream new point positions (same count keeps colors/sizes). Call `plot.refresh()` after. */
2257
+ setData(x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number>): void;
1182
2258
  bounds3(): Bounds3 | null;
2259
+ colorInfo(): ColorInfo | null;
2260
+ pickData(): {
2261
+ positions: Float32Array<ArrayBufferLike>;
2262
+ label: ((i: number) => string) | undefined;
2263
+ } | null;
2264
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
2265
+ dispose(): void;
2266
+ }
2267
+
2268
+ interface Quiver3DOptions {
2269
+ /** Arrow base points. */
2270
+ x: ArrayLike<number>;
2271
+ y: ArrayLike<number>;
2272
+ z: ArrayLike<number>;
2273
+ /** Vector components. */
2274
+ u: ArrayLike<number>;
2275
+ v: ArrayLike<number>;
2276
+ w: ArrayLike<number>;
2277
+ /** Multiply the vectors before drawing. Default 1. */
2278
+ scale?: number;
2279
+ color?: string | Color;
2280
+ /** Color arrows by magnitude via a colormap. */
2281
+ colorBy?: {
2282
+ colormap?: ColormapName;
2283
+ domain?: Range;
2284
+ };
2285
+ /** Arrowhead length as a fraction of the arrow. Default 0.28. */
2286
+ headSize?: number;
2287
+ name?: string;
2288
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2289
+ renderType?: RenderType;
2290
+ }
2291
+ /** A 3D vector field: each arrow is a shaft + a 4-wing arrowhead, drawn as lines. */
2292
+ declare class Quiver3DLayer implements Layer3D {
2293
+ readonly id: string;
2294
+ readonly name?: string;
2295
+ readonly colorCss?: string;
2296
+ private gl;
2297
+ private program;
2298
+ private vao;
2299
+ private buffer;
2300
+ private uniforms;
2301
+ private vertCount;
2302
+ private b3;
2303
+ private cInfo;
2304
+ private positions;
2305
+ private base;
2306
+ private scale;
2307
+ private headSize;
2308
+ private colorByOpt?;
2309
+ private usage;
2310
+ constructor(gl: WebGL2RenderingContext, opts: Quiver3DOptions);
2311
+ /** Build the arrow line geometry (shaft + 4-wing head) and (re)upload the vertex buffer. */
2312
+ private build;
2313
+ /** Stream a new vector field (arrows rebuilt). Call `plot.refresh()` after. */
2314
+ setData(x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number>, u: ArrayLike<number>, v: ArrayLike<number>, w: ArrayLike<number>): void;
2315
+ bounds3(): Bounds3 | null;
2316
+ colorInfo(): ColorInfo | null;
2317
+ pickData(): {
2318
+ positions: Float32Array<ArrayBufferLike>;
2319
+ } | null;
1183
2320
  draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1184
2321
  dispose(): void;
1185
2322
  }
@@ -1193,9 +2330,16 @@ interface SurfaceOptions {
1193
2330
  extentX?: Range;
1194
2331
  extentZ?: Range;
1195
2332
  colormap?: ColormapName;
2333
+ /** Series name (colorbar label / legend). */
2334
+ name?: string;
2335
+ /** Render the grid as a wireframe (lines) instead of a lit filled surface. */
2336
+ wireframe?: boolean;
2337
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2338
+ renderType?: RenderType;
1196
2339
  }
1197
2340
  declare class SurfaceLayer implements Layer3D {
1198
2341
  readonly id: string;
2342
+ readonly name?: string;
1199
2343
  private gl;
1200
2344
  private program;
1201
2345
  private vao;
@@ -1203,16 +2347,90 @@ declare class SurfaceLayer implements Layer3D {
1203
2347
  private uniforms;
1204
2348
  private vertexCount;
1205
2349
  private b3;
2350
+ private cmapName;
2351
+ private vDomain;
2352
+ private wireframe;
2353
+ private cols;
2354
+ private rows;
2355
+ private extentX;
2356
+ private extentZ;
2357
+ private usage;
1206
2358
  private lightDir;
1207
2359
  private ambient;
1208
2360
  constructor(gl: WebGL2RenderingContext, opts: SurfaceOptions);
2361
+ /** Build the mesh (positions/normals/colors or wireframe) and (re)upload the vertex buffer. */
2362
+ private build;
2363
+ /** Stream a new height grid (mesh/normals/wireframe rebuilt). Call `plot.refresh()` after. */
2364
+ setData(values: ArrayLike<number>, opts?: {
2365
+ cols?: number;
2366
+ rows?: number;
2367
+ extentX?: Range;
2368
+ extentZ?: Range;
2369
+ }): void;
1209
2370
  bounds3(): Bounds3;
2371
+ colorInfo(): ColorInfo;
1210
2372
  /** Set the light direction (world space) and ambient term (0..1). */
1211
2373
  setLight(dir: [number, number, number], ambient: number): void;
1212
2374
  draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1213
2375
  dispose(): void;
1214
2376
  }
1215
2377
 
2378
+ interface VolumeOptions {
2379
+ /** Scalar volume, length `nx*ny*nz`, indexed `x + y*nx + z*nx*ny`. */
2380
+ values: ArrayLike<number>;
2381
+ dims: [number, number, number];
2382
+ /** World extent of the volume. Defaults to unit indices. */
2383
+ extent?: {
2384
+ x: Range;
2385
+ y: Range;
2386
+ z: Range;
2387
+ };
2388
+ colormap?: ColormapName;
2389
+ /** Value range mapped to the colormap + opacity. Defaults to the data min/max. */
2390
+ domain?: Range;
2391
+ /** Overall opacity multiplier. Default 1. */
2392
+ density?: number;
2393
+ name?: string;
2394
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2395
+ renderType?: RenderType;
2396
+ }
2397
+ /**
2398
+ * Direct volume rendering: GPU raymarching through a 3D texture with front-to-back
2399
+ * alpha compositing and a colormap transfer function. Draws the volume's bounding
2400
+ * box (back faces) and integrates each ray across the box interior.
2401
+ */
2402
+ declare class VolumeLayer implements Layer3D {
2403
+ readonly id: string;
2404
+ readonly name?: string;
2405
+ private gl;
2406
+ private program;
2407
+ private vao;
2408
+ private buffer;
2409
+ private tex;
2410
+ private lut;
2411
+ private uniforms;
2412
+ private b3;
2413
+ private ext;
2414
+ private density;
2415
+ private cmapName;
2416
+ private vDomain;
2417
+ private dims;
2418
+ private domainOpt?;
2419
+ private usage;
2420
+ private camLocal;
2421
+ constructor(gl: WebGL2RenderingContext, opts: VolumeOptions);
2422
+ /** Normalize the scalar field and (re)upload it into the R8 3D texture. */
2423
+ private uploadVolume;
2424
+ /** Stream a new scalar volume (same dims); re-uploads the 3D texture. Call `plot.refresh()` after. */
2425
+ setData(values: ArrayLike<number>): void;
2426
+ bounds3(): Bounds3;
2427
+ colorInfo(): ColorInfo;
2428
+ /** Set the camera position in world space; converted to the volume's [0,1] local space. */
2429
+ setCamera(worldEye: [number, number, number]): void;
2430
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
2431
+ dispose(): void;
2432
+ }
2433
+
1216
2434
  interface Plot3DOptions {
1217
2435
  background?: [number, number, number, number];
1218
2436
  azimuth?: number;
@@ -1226,6 +2444,22 @@ interface Plot3DOptions {
1226
2444
  };
1227
2445
  /** Render a small on-canvas panel with light-angle + ambient sliders. */
1228
2446
  lightControls?: boolean;
2447
+ /** Plot title, drawn top-center. */
2448
+ title?: string;
2449
+ /** Show a legend of named solid-colored layers. Default false. */
2450
+ legend?: boolean;
2451
+ /** Show a colorbar for the first colormapped layer. Default true when one exists. */
2452
+ colorbar?: boolean | {
2453
+ label?: string;
2454
+ };
2455
+ /** Hover tooltip on the nearest pickable point. Default true. */
2456
+ hover?: boolean;
2457
+ /** Show a reset-view (home) button. Default true. */
2458
+ resetButton?: boolean;
2459
+ /** Draw grid lines on the back walls of the cube. Default true. */
2460
+ gridPlanes?: boolean;
2461
+ /** Auto-orbit the camera: `true` for a default speed, or radians/frame. Default off. */
2462
+ autoRotate?: boolean | number;
1229
2463
  }
1230
2464
  /** A 3D scatter/surface plot with an orbit camera, axis ticks, and lighting. */
1231
2465
  declare class Plot3D {
@@ -1253,14 +2487,51 @@ declare class Plot3D {
1253
2487
  private tickBuf;
1254
2488
  private tickCount;
1255
2489
  private labels;
2490
+ /** Tick positions in cube space [-1,1], per axis, for the grid planes. */
2491
+ private tickCube;
2492
+ private gridPlanes;
2493
+ private gridVao;
2494
+ private gridBuf;
2495
+ /** Normalize params (world→cube: `cube = s*world + t`), for the volume camera. */
2496
+ private norm;
2497
+ /** Auto-orbit speed (rad/frame); 0 = off. Paused while the pointer is down. */
2498
+ private autoRotateSpeed;
2499
+ private rotating;
2500
+ private interacting;
1256
2501
  private lightAz;
1257
2502
  private lightEl;
1258
2503
  private ambient;
1259
2504
  private controlsEl;
2505
+ private title?;
2506
+ private showLegend;
2507
+ private colorbarOpt;
2508
+ private legendDiv;
2509
+ private colorbarDiv;
2510
+ private tooltip;
2511
+ private resetBtn;
2512
+ private hoverEnabled;
2513
+ /** Screen position (device px) of the picked point, for the highlight ring. */
2514
+ private hoverHit;
2515
+ /** Initial camera, restored by {@link resetView}. */
2516
+ private initialAz;
2517
+ private initialEl;
2518
+ private initialDist;
1260
2519
  constructor(container: HTMLElement, options?: Plot3DOptions);
1261
2520
  private bindLineVao;
1262
2521
  addSurface(opts: SurfaceOptions): SurfaceLayer;
1263
2522
  addPointCloud(opts: PointCloudOptions): PointCloudLayer;
2523
+ /** A 3D polyline / path. */
2524
+ addLine3D(opts: Line3DOptions): Line3DLayer;
2525
+ /** 3D bars (columns) on an x/z grid, lit and optionally colormapped. */
2526
+ addBar3D(opts: Bar3DOptions): Bar3DLayer;
2527
+ /** A 3D vector field (arrows), optionally colored by magnitude. */
2528
+ addQuiver3D(opts: Quiver3DOptions): Quiver3DLayer;
2529
+ /** 3D iso-height contour lines of a grid, stacked at their level heights. */
2530
+ addContour3D(opts: Contour3DOptions): Contour3DLayer;
2531
+ /** A marching-cubes isosurface of a 3D scalar volume (lit, solid-colored). */
2532
+ addIsosurface(opts: IsosurfaceOptions): IsosurfaceLayer;
2533
+ /** Direct volume rendering (GPU raymarch) of a 3D scalar field. */
2534
+ addVolume(opts: VolumeOptions): VolumeLayer;
1264
2535
  /** Update the light direction (azimuth/elevation, radians) and ambient (0..1). */
1265
2536
  setLight(params: {
1266
2537
  azimuth?: number;
@@ -1268,6 +2539,18 @@ declare class Plot3D {
1268
2539
  ambient?: number;
1269
2540
  }): void;
1270
2541
  private lightDir;
2542
+ /** Auto-orbit the camera. `true` = default speed, number = radians/frame, `false`/0 stops. */
2543
+ setAutoRotate(speed: number | boolean): void;
2544
+ /** Restore the initial camera orientation and zoom. */
2545
+ resetView(): void;
2546
+ /** Nearest pickable point to the cursor. Screen coords are device px. */
2547
+ private pick;
2548
+ /** Show/hide the hover tooltip + highlight ring for the point under the cursor. */
2549
+ private updateHover;
2550
+ /** Remove a layer, re-fit, and redraw. */
2551
+ removeLayer(layer: Layer3D): void;
2552
+ /** Re-fit the axes to the data and redraw — call after a layer's `setData(...)`. */
2553
+ refresh(): void;
1271
2554
  destroy(): void;
1272
2555
  private recompute;
1273
2556
  /** Build tick-mark line geometry + tick/title labels from the data bounds. */
@@ -1275,12 +2558,41 @@ declare class Plot3D {
1275
2558
  private resize;
1276
2559
  requestRender(): void;
1277
2560
  private viewProj;
2561
+ /** Build + draw grid lines on the 3 back walls (cube space) for the current eye. */
2562
+ private drawGridPlanes;
1278
2563
  render(): void;
2564
+ /** DOM legend of named, solid-colored layers. */
2565
+ private updateLegend;
2566
+ /** DOM colorbar for the first colormapped layer (gradient + value range). */
2567
+ private updateColorbar;
1279
2568
  private drawLabels;
1280
2569
  private attachControls;
1281
2570
  private buildControls;
1282
2571
  }
1283
2572
 
2573
+ /**
2574
+ * Marching cubes: extract a triangle-mesh isosurface from a 3D scalar volume.
2575
+ * Pure and unit-tested. Uses the canonical Bourke/Bloyd edge + triangle tables.
2576
+ *
2577
+ * The volume is indexed `x + y*nx + z*nx*ny`. A corner is "inside" when its value
2578
+ * is below `isoLevel`. Vertex positions are linearly interpolated along the crossed
2579
+ * cube edges; normals come from the (central-difference) volume gradient so the
2580
+ * surface shades smoothly.
2581
+ */
2582
+
2583
+ /**
2584
+ * Extract the isosurface of `values` (dims `nx*ny*nz`, index `x + y*nx + z*nx*ny`)
2585
+ * at `isoLevel`. Returns a triangle soup of world-space positions + smooth normals.
2586
+ */
2587
+ declare function marchingCubes(values: ArrayLike<number>, dims: [number, number, number], isoLevel: number, extent?: {
2588
+ x: Range;
2589
+ y: Range;
2590
+ z: Range;
2591
+ }): {
2592
+ positions: Float32Array;
2593
+ normals: Float32Array;
2594
+ };
2595
+
1284
2596
  /**
1285
2597
  * Owns the tick configuration for one axis and resolves the final tick list
1286
2598
  * against a scale. Modes: auto (delegates to the scale), custom (array), or
@@ -1367,14 +2679,259 @@ interface Density {
1367
2679
  */
1368
2680
  declare function kde(values: ArrayLike<number>, lo: number, hi: number, points?: number, bandwidth?: number): Density;
1369
2681
 
2682
+ /** Map a layer's {@link RenderType} to a WebGL buffer-usage hint (default STATIC_DRAW). */
2683
+ declare function bufferUsage(gl: WebGL2RenderingContext, renderType?: RenderType): number;
1370
2684
  /** Compile + link a vertex/fragment program. */
1371
2685
  declare function createProgram(gl: WebGL2RenderingContext, vert: string, frag: string): WebGLProgram;
1372
2686
  /** Cache uniform locations for a program by name. */
1373
2687
  declare function uniformLocations(gl: WebGL2RenderingContext, program: WebGLProgram, names: string[]): Record<string, WebGLUniformLocation | null>;
1374
2688
 
2689
+ /**
2690
+ * Ear-clipping polygon triangulation with hole support.
2691
+ *
2692
+ * A faithful reimplementation of the well-known ear-clipping algorithm (as
2693
+ * popularized by mapbox/earcut, ISC). Input is a flat `[x0,y0,x1,y1,…]`
2694
+ * coordinate array with optional hole start-indices; output is a flat list of
2695
+ * triangle vertex indices into that array. Pure and unit-tested.
2696
+ *
2697
+ * For rings above {@link Z_ORDER_THRESHOLD} vertices it switches on the z-order
2698
+ * (Morton) curve acceleration: each node gets a 32-bit Morton code, the nodes
2699
+ * are merge-sorted into a secondary z-linked list, and the "is this an ear?"
2700
+ * test only scans candidate points whose Morton code falls in the ear's
2701
+ * bounding-box range — turning the inner loop from O(n) into ~O(1) amortized,
2702
+ * so the whole triangulation goes from O(n²) to ~O(n log n). Small rings (most
2703
+ * vector-tile polygons) skip the hashing entirely to avoid its setup cost.
2704
+ */
2705
+ /**
2706
+ * Triangulate a polygon. `holeIndices[k]` is the vertex index (not coordinate
2707
+ * index) where hole `k` begins. Returns triangle vertex indices in groups of 3.
2708
+ */
2709
+ declare function earcut(data: number[], holeIndices?: number[], dim?: number): number[];
2710
+
2711
+ /** Simple moving average over `period` samples. */
2712
+ declare function sma(values: ArrayLike<number>, period: number): Float64Array;
2713
+ /** Weighted moving average (linear weights 1..period, newest heaviest). */
2714
+ declare function wma(values: ArrayLike<number>, period: number): Float64Array;
2715
+ /**
2716
+ * Exponential moving average, α = 2/(period+1). Seeded with the SMA of the first
2717
+ * `period` samples at index `period-1` (the standard convention).
2718
+ */
2719
+ declare function ema(values: ArrayLike<number>, period: number): Float64Array;
2720
+ /** Rolling population standard deviation over `period` samples. */
2721
+ declare function rollingStd(values: ArrayLike<number>, period: number): Float64Array;
2722
+ interface BollingerBands {
2723
+ middle: Float64Array;
2724
+ upper: Float64Array;
2725
+ lower: Float64Array;
2726
+ }
2727
+ /** Bollinger Bands: SMA(period) ± `k`·rollingStd(period). Defaults 20, 2. */
2728
+ declare function bollinger(close: ArrayLike<number>, period?: number, k?: number): BollingerBands;
2729
+ /** Wilder's RSI over `period` (default 14). Values in 0..100; warm-up is NaN. */
2730
+ declare function rsi(close: ArrayLike<number>, period?: number): Float64Array;
2731
+ interface Macd {
2732
+ macd: Float64Array;
2733
+ signal: Float64Array;
2734
+ histogram: Float64Array;
2735
+ }
2736
+ /** MACD: EMA(fast) − EMA(slow), its EMA(signal) line, and the histogram. Defaults 12/26/9. */
2737
+ declare function macd(close: ArrayLike<number>, fast?: number, slow?: number, signalPeriod?: number): Macd;
2738
+ /**
2739
+ * Volume-weighted average price, cumulative from the first sample: running
2740
+ * Σ(typical·volume) / Σ(volume), where typical = (high+low+close)/3.
2741
+ */
2742
+ declare function vwap(high: ArrayLike<number>, low: ArrayLike<number>, close: ArrayLike<number>, volume: ArrayLike<number>): Float64Array;
2743
+ /** True range per bar: max(H−L, |H−prevC|, |L−prevC|). First bar is H−L. */
2744
+ declare function trueRange(high: ArrayLike<number>, low: ArrayLike<number>, close: ArrayLike<number>): Float64Array;
2745
+ /** Wilder's Average True Range over `period` (default 14). */
2746
+ declare function atr(high: ArrayLike<number>, low: ArrayLike<number>, close: ArrayLike<number>, period?: number): Float64Array;
2747
+ /** Index of the first non-NaN value (−1 if all NaN). Handy for trimming warm-up. */
2748
+ declare function firstFinite(values: ArrayLike<number>): number;
2749
+
2750
+ /**
2751
+ * Chart-type transforms: turn raw OHLC(V) into the geometry a specialist finance
2752
+ * chart needs. Each returns plain arrays you render with existing layers
2753
+ * (candlestick, bar, area, scatter) — see the `Plot.add*` helpers that wrap them.
2754
+ */
2755
+ interface Ohlc {
2756
+ open: ArrayLike<number>;
2757
+ high: ArrayLike<number>;
2758
+ low: ArrayLike<number>;
2759
+ close: ArrayLike<number>;
2760
+ }
2761
+ interface OhlcArrays {
2762
+ open: Float64Array;
2763
+ high: Float64Array;
2764
+ low: Float64Array;
2765
+ close: Float64Array;
2766
+ }
2767
+ /**
2768
+ * Heikin-Ashi candles — a smoothed OHLC that filters noise and makes trends
2769
+ * obvious. Output has the same length; feed it to a candlestick layer.
2770
+ *
2771
+ * haClose = (o+h+l+c)/4
2772
+ * haOpen = (prevHaOpen + prevHaClose)/2 (seed: (o₀+c₀)/2)
2773
+ * haHigh = max(h, haOpen, haClose)
2774
+ * haLow = min(l, haOpen, haClose)
2775
+ */
2776
+ declare function heikinAshi(d: Ohlc): OhlcArrays;
2777
+ /** One brick / box for Renko & Line-break (each renders as a wickless candle body). */
2778
+ interface Brick {
2779
+ /** Sequential column index (0..n-1); bricks are evenly spaced, time is discarded. */
2780
+ x: number;
2781
+ open: number;
2782
+ close: number;
2783
+ /** `true` when close > open (up brick). */
2784
+ up: boolean;
2785
+ }
2786
+ /**
2787
+ * Renko bricks from a close series. A new brick is emitted each time price moves
2788
+ * a full `brickSize` from the last brick's close (multiple bricks if it jumps
2789
+ * several sizes). Time is discarded — bricks are placed at successive indices.
2790
+ */
2791
+ declare function renko(close: ArrayLike<number>, brickSize: number): Brick[];
2792
+ /**
2793
+ * Three-line-break (generalised to `lines`): a new up brick when close exceeds
2794
+ * the highest close of the last `lines` bricks, a down brick when it breaks the
2795
+ * lowest; otherwise nothing. Bricks are placed at successive indices.
2796
+ */
2797
+ declare function lineBreak(close: ArrayLike<number>, lines?: number): Brick[];
2798
+ /** One P&F column: a run of X's (rising) or O's (falling) spanning `from`→`to`. */
2799
+ interface PfColumn {
2800
+ col: number;
2801
+ kind: "X" | "O";
2802
+ from: number;
2803
+ to: number;
2804
+ /** Box centers filled in this column (for plotting the X/O glyphs). */
2805
+ boxes: number[];
2806
+ }
2807
+ /**
2808
+ * Point & Figure columns. Price is quantised to `boxSize`; a column of X's grows
2809
+ * while price rises, O's while it falls, and the column flips only after a
2810
+ * `reversal`-box move against it. Time is discarded.
2811
+ */
2812
+ declare function pointAndFigure(high: ArrayLike<number>, low: ArrayLike<number>, boxSize: number, reversal?: number): PfColumn[];
2813
+ interface VolumeProfile {
2814
+ /** Bin center price for each level (length = bins). */
2815
+ levels: Float64Array;
2816
+ /** Total volume traded in each price bin. */
2817
+ volume: Float64Array;
2818
+ binSize: number;
2819
+ priceMin: number;
2820
+ priceMax: number;
2821
+ /** Bin index of the highest-volume level (the Point of Control). */
2822
+ pocIndex: number;
2823
+ }
2824
+ /**
2825
+ * Volume profile — a histogram of traded volume by price level. Plot it as
2826
+ * horizontal bars (`orientation:"h"`) with `levels` on the y axis.
2827
+ */
2828
+ declare function volumeProfile(price: ArrayLike<number>, volume: ArrayLike<number>, bins?: number): VolumeProfile;
2829
+ interface DepthCurves {
2830
+ /** Bid side: prices ascending toward mid, cumulative volume (best bid = largest cum). */
2831
+ bidPrice: Float64Array;
2832
+ bidCum: Float64Array;
2833
+ /** Ask side: prices ascending away from mid, cumulative volume. */
2834
+ askPrice: Float64Array;
2835
+ askCum: Float64Array;
2836
+ }
2837
+ /**
2838
+ * Order-book depth curves. `bids`/`asks` are `[price, size]` pairs (any order);
2839
+ * returns cumulative-volume step curves ready for two step-area layers.
2840
+ */
2841
+ declare function depth(bids: ArrayLike<readonly [number, number]>, asks: ArrayLike<readonly [number, number]>): DepthCurves;
2842
+
2843
+ /**
2844
+ * Convenience builders for specialist finance charts. Each takes a {@link Plot}
2845
+ * and composes existing layers from a transform/indicator — mirroring the
2846
+ * `addMap(plot, …)` free-function style. Import from `@photonviz/core`.
2847
+ */
2848
+
2849
+ /** Raw OHLC input shared by the candle-style helpers. */
2850
+ interface OhlcInput {
2851
+ x: ArrayLike<number>;
2852
+ open: ArrayLike<number>;
2853
+ high: ArrayLike<number>;
2854
+ low: ArrayLike<number>;
2855
+ close: ArrayLike<number>;
2856
+ }
2857
+ interface HeikinAshiOptions extends Omit<CandlestickOptions, "open" | "high" | "low" | "close"> {
2858
+ open: ArrayLike<number>;
2859
+ high: ArrayLike<number>;
2860
+ low: ArrayLike<number>;
2861
+ close: ArrayLike<number>;
2862
+ }
2863
+ /** Heikin-Ashi candles: smooth the OHLC, then draw it as a candlestick layer. */
2864
+ declare function addHeikinAshi(plot: Plot, opts: HeikinAshiOptions): CandlestickLayer;
2865
+ interface RenkoOptions {
2866
+ close: ArrayLike<number>;
2867
+ /** Fixed brick height in price units. */
2868
+ brickSize: number;
2869
+ upColor?: string | Color;
2870
+ downColor?: string | Color;
2871
+ name?: string;
2872
+ yAxis?: string;
2873
+ renderType?: RenderType;
2874
+ }
2875
+ /**
2876
+ * Renko chart — bricks at successive integer indices (time discarded). Rendered
2877
+ * as wickless candles, so pair it with an `ordinal-time`/linear x axis.
2878
+ */
2879
+ declare function addRenko(plot: Plot, opts: RenkoOptions): CandlestickLayer;
2880
+ interface VolumeProfileOptions {
2881
+ /** Price per sample (typically close). */
2882
+ price: ArrayLike<number>;
2883
+ volume: ArrayLike<number>;
2884
+ /** Number of price bins. Default 24. */
2885
+ bins?: number;
2886
+ color?: string | Color;
2887
+ /** Highlight the Point-of-Control bin with this color. */
2888
+ pocColor?: string | Color;
2889
+ name?: string;
2890
+ yAxis?: string;
2891
+ renderType?: RenderType;
2892
+ }
2893
+ /** Volume-by-price histogram as horizontal bars (price on the y axis). */
2894
+ declare function addVolumeProfile(plot: Plot, opts: VolumeProfileOptions): BarLayer;
2895
+ interface BollingerOptions {
2896
+ x: ArrayLike<number>;
2897
+ close: ArrayLike<number>;
2898
+ period?: number;
2899
+ k?: number;
2900
+ /** Line color for the bands + middle. Default light blue. */
2901
+ color?: string | Color;
2902
+ /** Fill color between the bands (omit to skip the fill). */
2903
+ bandColor?: string | Color;
2904
+ width?: number;
2905
+ yAxis?: string;
2906
+ renderType?: RenderType;
2907
+ }
2908
+ /** Bollinger Bands: a shaded band between upper/lower plus the three lines. */
2909
+ interface BollingerHandle {
2910
+ band?: AreaLayer;
2911
+ upper: LineLayer;
2912
+ middle: LineLayer;
2913
+ lower: LineLayer;
2914
+ }
2915
+ declare function addBollinger(plot: Plot, opts: BollingerOptions): BollingerHandle;
2916
+ interface DepthOptions {
2917
+ /** `[price, size]` levels (any order). */
2918
+ bids: ArrayLike<readonly [number, number]>;
2919
+ asks: ArrayLike<readonly [number, number]>;
2920
+ bidColor?: string | Color;
2921
+ askColor?: string | Color;
2922
+ yAxis?: string;
2923
+ renderType?: RenderType;
2924
+ }
2925
+ /** Order-book depth: cumulative bid/ask volume as two filled areas. */
2926
+ interface DepthHandle {
2927
+ bid: AreaLayer;
2928
+ ask: AreaLayer;
2929
+ }
2930
+ declare function addDepth(plot: Plot, opts: DepthOptions): DepthHandle;
2931
+
1375
2932
  /** Parse a CSS hex/rgb color string into normalized RGBA (0..1). */
1376
2933
  declare function parseColor(input: string): [number, number, number, number];
1377
2934
  /** Normalized RGBA (0..1) back to a CSS `rgba(...)` string. */
1378
2935
  declare function toColorCss(c: readonly [number, number, number, number]): string;
1379
2936
 
1380
- export { AreaLayer, type AreaOptions, Axis, type AxisConfig, type AxisFrame, type AxisScaleOptions, BarLayer, type BarOptions, type Bounds, type Bounds3, type BoxGroup, BoxLayer, type BoxOptions, type BoxStats, CandlestickLayer, type CandlestickOptions, type Color, type ColormapName, ContourLayer, type ContourOptions, type Density, type Dim, type DrawState, ErrorBarLayer, type ErrorBarOptions, HeatmapLayer, type HeatmapOptions, HexbinLayer, type HexbinOptions, type Histogram, type HoverReadoutRow, type InteractionMode, type Layer, type Layer3D, type Layout, LineLayer, type LineOptions, LinearScale, LogScale, type PickMode, Plot, Plot3D, type Plot3DOptions, type PlotOptions, PointCloudLayer, type PointCloudOptions, type PolarLineOptions, type PolarOptions, PolarPlot, type PolarScatterOptions, type PolarSeries, QuiverLayer, type QuiverOptions, type RGB, type Range, type Scale, type ScaleType, ScatterLayer, type ScatterOptions, type Spectrogram, StemLayer, type StemOptions, SurfaceLayer, type SurfaceOptions, TRANSFORM_GLSL, TRANSFORM_UNIFORMS, type Theme, type Tick, type TicksSpec, TimeScale, type ToolbarHost, type ToolbarTheme, type YAxisOptions, autoTicks, boxStats, colormap, createProgram, createToolbar, darkTheme, defaultFormat, fft, histogram, kde, lightTheme, makeScale, parseColor, quantileSorted, resolveTicks, setTransformUniforms, spectrogram, toColorCss, uniformLocations, withMinorTicks };
2937
+ export { type Annotation, AreaLayer, type AreaOptions, type AreaSeries, Axis, type AxisConfig, type AxisFrame, type AxisScaleOptions, Bar3DLayer, type Bar3DOptions, BarLayer, type BarOptions, type BarSeries, type BollingerBands, type BollingerHandle, type BollingerOptions, type Bounds, type Bounds3, type BoxGroup, BoxLayer, type BoxOptions, type BoxStats, type Brick, type Candle, type CandlestickData, CandlestickLayer, type CandlestickOptions, CategoricalScale, type Color, type ColorInfo, type ColormapName, Contour3DLayer, type Contour3DOptions, ContourLayer, type ContourOptions, type Density, type DepthCurves, type DepthHandle, type DepthOptions, type Dim, type DrawState, ErrorBarLayer, type ErrorBarOptions, type ForceLayoutOptions, type GraphInput, GraphLayer, type GraphOptions, type GroupedBarOptions, HeatmapLayer, type HeatmapOptions, type HeikinAshiOptions, HexbinLayer, type HexbinOptions, type Histogram, type HoverReadoutRow, ImageLayer, type ImageOptions, type ImageSource, type InteractionMode, IsosurfaceLayer, type IsosurfaceOptions, type Layer, type Layer3D, type Layout, type LegendOptions, Line3DLayer, type Line3DOptions, LineLayer, type LineOptions, LinearScale, LogScale, type Macd, type MarkerShape, type Ohlc, type OhlcArrays, type OhlcInput, OhlcLayer, type OhlcOptions, OrdinalTimeScale, type Patch, PatchesLayer, type PatchesOptions, type PfColumn, type PickMode, PieLayer, type PieOptions, Plot, Plot3D, type Plot3DOptions, type PlotOptions, type PlotTitleOptions, PointCloudLayer, type PointCloudOptions, type PolarLineOptions, type PolarOptions, PolarPlot, type PolarScatterOptions, type PolarSeries, Quiver3DLayer, type Quiver3DOptions, QuiverLayer, type QuiverOptions, type RGB, type Range, type RenderType, type RenkoOptions, type ResolvedAxisStyle, type Scale, type ScaleType, ScatterLayer, type ScatterOptions, type Spectrogram, type StackedAreaOptions, type StackedBarOptions, StemLayer, type StemOptions, SurfaceLayer, type SurfaceOptions, TRANSFORM_GLSL, TRANSFORM_UNIFORMS, type Theme, type Tick, type TicksSpec, TimeScale, type ToolbarHost, type ToolbarTheme, VolumeLayer, type VolumeOptions, type VolumeProfile, type VolumeProfileOptions, type YAxisOptions, addBollinger, addDepth, addHeikinAshi, addRenko, addVolumeProfile, atr, autoTicks, bollinger, boxStats, bufferUsage, colormap, colormapLUT, createProgram, createToolbar, darkTheme, defaultFormat, depth, earcut, ema, fft, firstFinite, forceLayout, heikinAshi, histogram, kde, lightTheme, lineBreak, linkX, macd, makeScale, marchingCubes, parseColor, pointAndFigure, quantileSorted, renko, resolveAxisStyle, resolveTicks, rollingStd, rsi, setTransformUniforms, sma, spectrogram, toColorCss, trueRange, uniformLocations, volumeProfile, vwap, withMinorTicks, wma };