@photonviz/core 0.3.0 → 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
@@ -68,6 +68,13 @@ type Dim = "x" | "y";
68
68
  * - `box-y` drag selects a y-range only (full width band) — Y-only zoom
69
69
  */
70
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";
71
78
  type Range = readonly [number, number];
72
79
  interface Bounds {
73
80
  x: Range;
@@ -131,6 +138,8 @@ interface AreaOptions {
131
138
  /** Lower edge(s). Number or per-point array — pass cumulative to stack. */
132
139
  base?: number | ArrayLike<number>;
133
140
  color?: string | Color;
141
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
142
+ renderType?: RenderType;
134
143
  name?: string;
135
144
  yAxis?: string;
136
145
  }
@@ -146,6 +155,7 @@ declare class AreaLayer implements Layer {
146
155
  private uniforms;
147
156
  private vertexCount;
148
157
  private color;
158
+ private usage;
149
159
  private xRef;
150
160
  private yRef;
151
161
  private xBounds;
@@ -179,6 +189,13 @@ interface BarOptions {
179
189
  */
180
190
  orientation?: "v" | "h";
181
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;
182
199
  name?: string;
183
200
  yAxis?: string;
184
201
  }
@@ -194,6 +211,8 @@ declare class BarLayer implements Layer {
194
211
  private uniforms;
195
212
  private count;
196
213
  private color;
214
+ private colorsInput?;
215
+ private usage;
197
216
  private barWidth;
198
217
  private offset;
199
218
  private orientation;
@@ -202,9 +221,11 @@ declare class BarLayer implements Layer {
202
221
  private xBounds;
203
222
  private yBounds;
204
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;
205
226
  private buildRects;
206
- /** Replace bar values and re-upload (for streaming). */
207
- 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;
208
229
  bounds(): {
209
230
  x: Range;
210
231
  y: Range;
@@ -228,6 +249,8 @@ interface BoxOptions {
228
249
  box?: boolean;
229
250
  /** Draw a violin (KDE) shape behind/instead of the box (default false). */
230
251
  violin?: boolean;
252
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
253
+ renderType?: RenderType;
231
254
  yAxis?: string;
232
255
  }
233
256
  declare class BoxLayer implements Layer {
@@ -247,7 +270,15 @@ declare class BoxLayer implements Layer {
247
270
  private lineCount;
248
271
  private pointStart;
249
272
  private pointCount;
273
+ private width;
274
+ private showBox;
275
+ private showViolin;
276
+ private usage;
250
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;
251
282
  bounds(): {
252
283
  x: Range;
253
284
  y: Range;
@@ -271,9 +302,29 @@ interface CandlestickOptions {
271
302
  downColor?: string | Color;
272
303
  /** Wick thickness in CSS px. Default 1.5. */
273
304
  wickWidth?: number;
305
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
306
+ renderType?: RenderType;
274
307
  name?: string;
275
308
  yAxis?: string;
276
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
+ }
277
328
  declare class CandlestickLayer implements Layer {
278
329
  readonly id: string;
279
330
  readonly name: string;
@@ -287,12 +338,120 @@ declare class CandlestickLayer implements Layer {
287
338
  private uBody;
288
339
  private uWick;
289
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;
290
355
  private count;
291
356
  private xRef;
292
357
  private yRef;
293
358
  private xBounds;
294
359
  private yBounds;
295
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;
296
455
  bounds(): {
297
456
  x: Range;
298
457
  y: Range;
@@ -326,6 +485,8 @@ interface ContourOptions {
326
485
  /** Single line color; if omitted, levels are colored by a colormap. */
327
486
  color?: string | Color;
328
487
  colormap?: ColormapName;
488
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
489
+ renderType?: RenderType;
329
490
  yAxis?: string;
330
491
  }
331
492
  declare class ContourLayer implements Layer {
@@ -340,7 +501,17 @@ declare class ContourLayer implements Layer {
340
501
  private xRef;
341
502
  private yRef;
342
503
  private ext;
504
+ private cols;
505
+ private rows;
506
+ private levelsOpt;
507
+ private cmap;
508
+ private fixedColor;
509
+ private usage;
343
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;
344
515
  bounds(): {
345
516
  x: Range;
346
517
  y: Range;
@@ -372,9 +543,20 @@ interface ErrorBarOptions {
372
543
  band?: boolean;
373
544
  /** Band fill opacity. Default 0.2. */
374
545
  bandOpacity?: number;
546
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
547
+ renderType?: RenderType;
375
548
  name?: string;
376
549
  yAxis?: string;
377
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
+ }
378
560
  declare class ErrorBarLayer implements Layer {
379
561
  readonly id: string;
380
562
  readonly name: string;
@@ -395,6 +577,7 @@ declare class ErrorBarLayer implements Layer {
395
577
  private bandOpacity;
396
578
  private showWhiskers;
397
579
  private showBand;
580
+ private usage;
398
581
  private segCount;
399
582
  private capCount;
400
583
  private bandVerts;
@@ -403,6 +586,10 @@ declare class ErrorBarLayer implements Layer {
403
586
  private xBounds;
404
587
  private yBounds;
405
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;
406
593
  bounds(): {
407
594
  x: Range;
408
595
  y: Range;
@@ -421,9 +608,20 @@ interface GraphOptions {
421
608
  /** Node diameter in CSS pixels. Default 10. */
422
609
  nodeSize?: number;
423
610
  edgeColor?: string | Color;
611
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
612
+ renderType?: RenderType;
424
613
  name?: string;
425
614
  yAxis?: string;
426
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
+ }
427
625
  /** A node-link graph: edges as line segments, nodes as round points. */
428
626
  declare class GraphLayer implements Layer {
429
627
  readonly id: string;
@@ -446,7 +644,15 @@ declare class GraphLayer implements Layer {
446
644
  private yRef;
447
645
  private xBounds;
448
646
  private yBounds;
647
+ private usage;
449
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;
450
656
  bounds(): {
451
657
  x: Range;
452
658
  y: Range;
@@ -470,6 +676,8 @@ interface HeatmapOptions {
470
676
  domain?: Range;
471
677
  /** Bilinear filtering (default true) vs. hard cells. */
472
678
  smooth?: boolean;
679
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
680
+ renderType?: RenderType;
473
681
  yAxis?: string;
474
682
  }
475
683
  declare class HeatmapLayer implements Layer {
@@ -484,7 +692,15 @@ declare class HeatmapLayer implements Layer {
484
692
  private xRef;
485
693
  private yRef;
486
694
  private ext;
695
+ private lut;
696
+ private fixedDomain;
697
+ private cols;
698
+ private rows;
487
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;
488
704
  bounds(): {
489
705
  x: Range;
490
706
  y: Range;
@@ -501,6 +717,8 @@ interface HexbinOptions {
501
717
  colormap?: ColormapName;
502
718
  /** Count range mapped to the colormap. Defaults to [1, maxCount]. */
503
719
  domain?: Range;
720
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
721
+ renderType?: RenderType;
504
722
  yAxis?: string;
505
723
  }
506
724
  declare class HexbinLayer implements Layer {
@@ -517,7 +735,15 @@ declare class HexbinLayer implements Layer {
517
735
  private yRef;
518
736
  private xBounds;
519
737
  private yBounds;
738
+ private cmap;
739
+ private explicitRadius;
740
+ private domain;
741
+ private usage;
520
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;
521
747
  bounds(): {
522
748
  x: Range;
523
749
  y: Range;
@@ -542,6 +768,8 @@ interface ImageOptions {
542
768
  opacity?: number;
543
769
  /** Called after an async (URL) image finishes loading — wire to `plot.requestRender`. */
544
770
  onLoad?: () => void;
771
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
772
+ renderType?: RenderType;
545
773
  name?: string;
546
774
  yAxis?: string;
547
775
  }
@@ -570,6 +798,10 @@ declare class ImageLayer implements Layer {
570
798
  private ready;
571
799
  private img;
572
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;
573
805
  private upload;
574
806
  bounds(): {
575
807
  x: Range;
@@ -629,6 +861,8 @@ interface LineOptions {
629
861
  * zoomed out (preserves peaks). Requires monotonic x; auto-detected. Default true.
630
862
  */
631
863
  decimate?: boolean;
864
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
865
+ renderType?: RenderType;
632
866
  }
633
867
  declare class LineLayer implements Layer {
634
868
  readonly id: string;
@@ -657,6 +891,7 @@ declare class LineLayer implements Layer {
657
891
  private monotonic;
658
892
  private gpuDec;
659
893
  private step?;
894
+ private usage;
660
895
  private xRef;
661
896
  private yRef;
662
897
  private xs;
@@ -707,6 +942,8 @@ interface PatchesOptions {
707
942
  domain?: Range;
708
943
  /** Fill opacity, 0..1. Default 1. */
709
944
  opacity?: number;
945
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
946
+ renderType?: RenderType;
710
947
  name?: string;
711
948
  yAxis?: string;
712
949
  }
@@ -730,7 +967,16 @@ declare class PatchesLayer implements Layer {
730
967
  private yRef;
731
968
  private xBounds;
732
969
  private yBounds;
970
+ private defRgba;
971
+ private opacity;
972
+ private cmap;
973
+ private domainOpt;
974
+ private usage;
733
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;
734
980
  bounds(): {
735
981
  x: Range;
736
982
  y: Range;
@@ -754,6 +1000,8 @@ interface PieOptions {
754
1000
  innerRadius?: number;
755
1001
  /** Angle of the first slice edge, radians. Default `Math.PI / 2` (12 o'clock). */
756
1002
  startAngle?: number;
1003
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1004
+ renderType?: RenderType;
757
1005
  name?: string;
758
1006
  yAxis?: string;
759
1007
  }
@@ -777,7 +1025,19 @@ declare class PieLayer implements Layer {
777
1025
  private yRef;
778
1026
  private xBounds;
779
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;
780
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;
781
1041
  bounds(): {
782
1042
  x: Range;
783
1043
  y: Range;
@@ -806,6 +1066,8 @@ interface QuiverOptions {
806
1066
  colormap?: ColormapName;
807
1067
  domain?: Range;
808
1068
  };
1069
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1070
+ renderType?: RenderType;
809
1071
  name?: string;
810
1072
  yAxis?: string;
811
1073
  }
@@ -825,6 +1087,9 @@ declare class QuiverLayer implements Layer {
825
1087
  private width;
826
1088
  private headSize;
827
1089
  private useVertexColor;
1090
+ private explicitScale;
1091
+ private colorBy;
1092
+ private usage;
828
1093
  private count;
829
1094
  private xRef;
830
1095
  private yRef;
@@ -832,6 +1097,10 @@ declare class QuiverLayer implements Layer {
832
1097
  private yBounds;
833
1098
  constructor(gl: WebGL2RenderingContext, opts: QuiverOptions);
834
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;
835
1104
  bounds(): {
836
1105
  x: Range;
837
1106
  y: Range;
@@ -865,6 +1134,8 @@ interface ScatterOptions {
865
1134
  /** Value range mapped to [0,1]. Defaults to the data min/max. */
866
1135
  domain?: Range;
867
1136
  };
1137
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1138
+ renderType?: RenderType;
868
1139
  }
869
1140
  declare class ScatterLayer implements Layer {
870
1141
  readonly id: string;
@@ -879,6 +1150,7 @@ declare class ScatterLayer implements Layer {
879
1150
  private count;
880
1151
  private size;
881
1152
  private marker;
1153
+ private usage;
882
1154
  private color;
883
1155
  private useVertexColor;
884
1156
  private labels?;
@@ -912,6 +1184,8 @@ interface StemOptions {
912
1184
  width?: number;
913
1185
  /** Tip marker diameter in CSS px (0 hides). Default 6. */
914
1186
  markerSize?: number;
1187
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1188
+ renderType?: RenderType;
915
1189
  name?: string;
916
1190
  yAxis?: string;
917
1191
  }
@@ -931,6 +1205,7 @@ declare class StemLayer implements Layer {
931
1205
  private width;
932
1206
  private markerSize;
933
1207
  private count;
1208
+ private usage;
934
1209
  private baseline;
935
1210
  private xRef;
936
1211
  private yRef;
@@ -939,6 +1214,10 @@ declare class StemLayer implements Layer {
939
1214
  private xBounds;
940
1215
  private yBounds;
941
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;
942
1221
  bounds(): {
943
1222
  x: Range;
944
1223
  y: Range;
@@ -1017,8 +1296,32 @@ declare class CategoricalScale implements Scale {
1017
1296
  ticks(): Tick[];
1018
1297
  formatTick(value: number): string;
1019
1298
  }
1020
- type ScaleType = "linear" | "log" | "time" | "categorical";
1021
- declare function makeScale(type: ScaleType, domain?: Range, factors?: string[]): Scale;
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;
1022
1325
 
1023
1326
  /** Pixel geometry of the plot, in CSS pixels. The plot region excludes margins. */
1024
1327
  interface Layout {
@@ -1083,6 +1386,12 @@ interface AxisScaleOptions {
1083
1386
  domain?: Range;
1084
1387
  /** Factor labels for a `"categorical"` axis (fixes the domain to the bands). */
1085
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>;
1086
1395
  }
1087
1396
  /** Legend placement + styling. `legend: true` uses all defaults. */
1088
1397
  interface LegendOptions {
@@ -1100,6 +1409,8 @@ interface YAxisOptions extends AxisConfig {
1100
1409
  domain?: Range;
1101
1410
  /** Factor labels for a `"categorical"` axis. */
1102
1411
  factors?: string[];
1412
+ /** Per-index epoch-ms timestamps for an `"ordinal-time"` axis. */
1413
+ times?: ArrayLike<number>;
1103
1414
  /** Which side to draw the axis on. Default `"right"` for secondary axes. */
1104
1415
  side?: "left" | "right";
1105
1416
  /** Axis + label color (secondary axes often match their series). */
@@ -1303,6 +1614,11 @@ declare class Plot {
1303
1614
  private hoverReadout?;
1304
1615
  /** Cursor position while the pointer is pressed, when `crosshair`. */
1305
1616
  private pressPx;
1617
+ private viewListeners;
1618
+ private cursorListeners;
1619
+ private lastEmittedX;
1620
+ private lastEmittedCursor;
1621
+ private linkedCursorX;
1306
1622
  private tooltip;
1307
1623
  /** A point clicked to pin its details, until another click clears it. */
1308
1624
  private selected;
@@ -1359,6 +1675,8 @@ declare class Plot {
1359
1675
  addStem(opts: StemOptions): StemLayer;
1360
1676
  addQuiver(opts: QuiverOptions): QuiverLayer;
1361
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;
1362
1680
  /** Filled polygons (choropleth-capable). Rings are triangulated with earcut. */
1363
1681
  addPatches(opts: PatchesOptions): PatchesLayer;
1364
1682
  /** A pie / donut chart. Set `equalAspect: true` on the plot so it stays circular. */
@@ -1399,6 +1717,10 @@ declare class Plot {
1399
1717
  }): BarLayer;
1400
1718
  /** Register an additional named y axis. Series opt in via `addLine({ yAxis })`. */
1401
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;
1402
1724
  removeLayer(layer: Layer): void;
1403
1725
  /** Configure ticks/format/title for the x axis or a y axis (default primary "y"). */
1404
1726
  setAxis(dim: Dim | string, config: Partial<AxisConfig>): void;
@@ -1408,6 +1730,18 @@ declare class Plot {
1408
1730
  y?: Range;
1409
1731
  yAxes?: Record<string, Range>;
1410
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;
1411
1745
  private setYDomain;
1412
1746
  setMode(mode: InteractionMode): void;
1413
1747
  getMode(): InteractionMode;
@@ -1420,6 +1754,8 @@ declare class Plot {
1420
1754
  private resize;
1421
1755
  requestRender(): void;
1422
1756
  private primaryY;
1757
+ /** Fire view/cursor listeners once the frame's x-domain + cursor are settled. */
1758
+ private emitLinks;
1423
1759
  render(): void;
1424
1760
  /** Named series that can appear in the legend: any layer exposing name + colorCss. */
1425
1761
  private legendEntries;
@@ -1466,6 +1802,21 @@ declare class Plot {
1466
1802
  private zoomAround;
1467
1803
  }
1468
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
+
1469
1820
  /** The subset of Plot the toolbar drives. Kept minimal to avoid an import cycle. */
1470
1821
  interface ToolbarHost {
1471
1822
  setMode(mode: InteractionMode): void;
@@ -1533,6 +1884,8 @@ interface PolarLineOptions {
1533
1884
  width?: number;
1534
1885
  /** Connect the last point back to the first. */
1535
1886
  closed?: boolean;
1887
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1888
+ renderType?: RenderType;
1536
1889
  }
1537
1890
  interface PolarScatterOptions {
1538
1891
  theta: ArrayLike<number>;
@@ -1541,6 +1894,8 @@ interface PolarScatterOptions {
1541
1894
  size?: number;
1542
1895
  /** Optional per-point labels (one per point), shown as the title of the click-pinned info box. */
1543
1896
  labels?: ArrayLike<string>;
1897
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
1898
+ renderType?: RenderType;
1544
1899
  }
1545
1900
  /** A live handle to update a polar series with new (theta, r) data. */
1546
1901
  interface PolarSeries {
@@ -1672,6 +2027,8 @@ interface Bar3DOptions {
1672
2027
  domain?: Range;
1673
2028
  };
1674
2029
  name?: string;
2030
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2031
+ renderType?: RenderType;
1675
2032
  }
1676
2033
  /** 3D bars (columns) on an x/z grid, lit like the surface and optionally colormapped. */
1677
2034
  declare class Bar3DLayer implements Layer3D {
@@ -1682,15 +2039,24 @@ declare class Bar3DLayer implements Layer3D {
1682
2039
  private program;
1683
2040
  private vao;
1684
2041
  private buffers;
2042
+ private instBuf;
1685
2043
  private uniforms;
1686
2044
  private count;
1687
2045
  private width;
1688
2046
  private b3;
1689
2047
  private cInfo;
1690
2048
  private positions;
2049
+ private base;
2050
+ private optWidth?;
2051
+ private colorByOpt?;
2052
+ private usage;
1691
2053
  private lightDir;
1692
2054
  private ambient;
1693
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;
1694
2060
  bounds3(): Bounds3 | null;
1695
2061
  colorInfo(): ColorInfo | null;
1696
2062
  pickData(): {
@@ -1716,6 +2082,8 @@ interface Contour3DOptions {
1716
2082
  color?: string | Color;
1717
2083
  colormap?: ColormapName;
1718
2084
  name?: string;
2085
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2086
+ renderType?: RenderType;
1719
2087
  }
1720
2088
  /**
1721
2089
  * 3D contour: iso-height lines of a grid, each drawn at its own level height
@@ -1733,7 +2101,24 @@ declare class Contour3DLayer implements Layer3D {
1733
2101
  private vertCount;
1734
2102
  private b3;
1735
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;
1736
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;
1737
2122
  bounds3(): Bounds3 | null;
1738
2123
  colorInfo(): ColorInfo | null;
1739
2124
  draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
@@ -1756,6 +2141,8 @@ interface IsosurfaceOptions {
1756
2141
  /** Fill opacity 0..1. Default 1. */
1757
2142
  opacity?: number;
1758
2143
  name?: string;
2144
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2145
+ renderType?: RenderType;
1759
2146
  }
1760
2147
  /** A marching-cubes isosurface of a 3D scalar volume, lit and solid-colored. */
1761
2148
  declare class IsosurfaceLayer implements Layer3D {
@@ -1771,9 +2158,18 @@ declare class IsosurfaceLayer implements Layer3D {
1771
2158
  private color;
1772
2159
  private opacity;
1773
2160
  private b3;
2161
+ private usage;
1774
2162
  private lightDir;
1775
2163
  private ambient;
1776
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;
1777
2173
  bounds3(): Bounds3 | null;
1778
2174
  /** Set the light direction (world space) and ambient term (0..1). */
1779
2175
  setLight(dir: [number, number, number], ambient: number): void;
@@ -1787,6 +2183,8 @@ interface Line3DOptions {
1787
2183
  z: ArrayLike<number>;
1788
2184
  color?: string | Color;
1789
2185
  name?: string;
2186
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2187
+ renderType?: RenderType;
1790
2188
  }
1791
2189
  /** A 3D polyline / path (`GL_LINE_STRIP`). */
1792
2190
  declare class Line3DLayer implements Layer3D {
@@ -1802,6 +2200,7 @@ declare class Line3DLayer implements Layer3D {
1802
2200
  private color;
1803
2201
  private b3;
1804
2202
  private positions;
2203
+ private usage;
1805
2204
  constructor(gl: WebGL2RenderingContext, opts: Line3DOptions);
1806
2205
  bounds3(): Bounds3 | null;
1807
2206
  pickData(): {
@@ -1831,6 +2230,8 @@ interface PointCloudOptions {
1831
2230
  labels?: ArrayLike<string>;
1832
2231
  /** Series name (legend / colorbar label). */
1833
2232
  name?: string;
2233
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2234
+ renderType?: RenderType;
1834
2235
  }
1835
2236
  declare class PointCloudLayer implements Layer3D {
1836
2237
  readonly id: string;
@@ -1849,6 +2250,7 @@ declare class PointCloudLayer implements Layer3D {
1849
2250
  private labels?;
1850
2251
  /** Interleaved pos(3)+color(3)+size(1); positions are streamed in place. */
1851
2252
  private data;
2253
+ private usage;
1852
2254
  constructor(gl: WebGL2RenderingContext, opts: PointCloudOptions);
1853
2255
  private updateBounds;
1854
2256
  /** Stream new point positions (same count keeps colors/sizes). Call `plot.refresh()` after. */
@@ -1883,6 +2285,8 @@ interface Quiver3DOptions {
1883
2285
  /** Arrowhead length as a fraction of the arrow. Default 0.28. */
1884
2286
  headSize?: number;
1885
2287
  name?: string;
2288
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2289
+ renderType?: RenderType;
1886
2290
  }
1887
2291
  /** A 3D vector field: each arrow is a shaft + a 4-wing arrowhead, drawn as lines. */
1888
2292
  declare class Quiver3DLayer implements Layer3D {
@@ -1898,7 +2302,16 @@ declare class Quiver3DLayer implements Layer3D {
1898
2302
  private b3;
1899
2303
  private cInfo;
1900
2304
  private positions;
2305
+ private base;
2306
+ private scale;
2307
+ private headSize;
2308
+ private colorByOpt?;
2309
+ private usage;
1901
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;
1902
2315
  bounds3(): Bounds3 | null;
1903
2316
  colorInfo(): ColorInfo | null;
1904
2317
  pickData(): {
@@ -1921,6 +2334,8 @@ interface SurfaceOptions {
1921
2334
  name?: string;
1922
2335
  /** Render the grid as a wireframe (lines) instead of a lit filled surface. */
1923
2336
  wireframe?: boolean;
2337
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2338
+ renderType?: RenderType;
1924
2339
  }
1925
2340
  declare class SurfaceLayer implements Layer3D {
1926
2341
  readonly id: string;
@@ -1935,9 +2350,23 @@ declare class SurfaceLayer implements Layer3D {
1935
2350
  private cmapName;
1936
2351
  private vDomain;
1937
2352
  private wireframe;
2353
+ private cols;
2354
+ private rows;
2355
+ private extentX;
2356
+ private extentZ;
2357
+ private usage;
1938
2358
  private lightDir;
1939
2359
  private ambient;
1940
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;
1941
2370
  bounds3(): Bounds3;
1942
2371
  colorInfo(): ColorInfo;
1943
2372
  /** Set the light direction (world space) and ambient term (0..1). */
@@ -1962,6 +2391,8 @@ interface VolumeOptions {
1962
2391
  /** Overall opacity multiplier. Default 1. */
1963
2392
  density?: number;
1964
2393
  name?: string;
2394
+ /** Buffer-usage hint; set `"dynamic"` when streaming via setData. Default `"static"`. */
2395
+ renderType?: RenderType;
1965
2396
  }
1966
2397
  /**
1967
2398
  * Direct volume rendering: GPU raymarching through a 3D texture with front-to-back
@@ -1983,8 +2414,15 @@ declare class VolumeLayer implements Layer3D {
1983
2414
  private density;
1984
2415
  private cmapName;
1985
2416
  private vDomain;
2417
+ private dims;
2418
+ private domainOpt?;
2419
+ private usage;
1986
2420
  private camLocal;
1987
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;
1988
2426
  bounds3(): Bounds3;
1989
2427
  colorInfo(): ColorInfo;
1990
2428
  /** Set the camera position in world space; converted to the volume's [0,1] local space. */
@@ -2241,6 +2679,8 @@ interface Density {
2241
2679
  */
2242
2680
  declare function kde(values: ArrayLike<number>, lo: number, hi: number, points?: number, bandwidth?: number): Density;
2243
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;
2244
2684
  /** Compile + link a vertex/fragment program. */
2245
2685
  declare function createProgram(gl: WebGL2RenderingContext, vert: string, frag: string): WebGLProgram;
2246
2686
  /** Cache uniform locations for a program by name. */
@@ -2268,9 +2708,230 @@ declare function uniformLocations(gl: WebGL2RenderingContext, program: WebGLProg
2268
2708
  */
2269
2709
  declare function earcut(data: number[], holeIndices?: number[], dim?: number): number[];
2270
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
+
2271
2932
  /** Parse a CSS hex/rgb color string into normalized RGBA (0..1). */
2272
2933
  declare function parseColor(input: string): [number, number, number, number];
2273
2934
  /** Normalized RGBA (0..1) back to a CSS `rgba(...)` string. */
2274
2935
  declare function toColorCss(c: readonly [number, number, number, number]): string;
2275
2936
 
2276
- export { type Annotation, AreaLayer, type AreaOptions, type AreaSeries, Axis, type AxisConfig, type AxisFrame, type AxisScaleOptions, Bar3DLayer, type Bar3DOptions, BarLayer, type BarOptions, type BarSeries, type Bounds, type Bounds3, type BoxGroup, BoxLayer, type BoxOptions, type BoxStats, CandlestickLayer, type CandlestickOptions, CategoricalScale, type Color, type ColorInfo, type ColormapName, Contour3DLayer, type Contour3DOptions, ContourLayer, type ContourOptions, type Density, type Dim, type DrawState, ErrorBarLayer, type ErrorBarOptions, type ForceLayoutOptions, type GraphInput, GraphLayer, type GraphOptions, type GroupedBarOptions, HeatmapLayer, type HeatmapOptions, 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 MarkerShape, type Patch, PatchesLayer, type PatchesOptions, 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 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 YAxisOptions, autoTicks, boxStats, colormap, colormapLUT, createProgram, createToolbar, darkTheme, defaultFormat, earcut, fft, forceLayout, histogram, kde, lightTheme, makeScale, marchingCubes, parseColor, quantileSorted, resolveAxisStyle, 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 };