@photonviz/core 0.2.1 → 0.3.0

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
  /**
@@ -136,6 +172,12 @@ interface BarOptions {
136
172
  width?: number;
137
173
  /** Shift bars by this many data units (use for grouped bars). */
138
174
  offset?: number;
175
+ /**
176
+ * `"v"` (default) draws vertical bars: `x` positions along the x axis, `y`
177
+ * values along the y axis. `"h"` draws horizontal bars: `x` positions along the
178
+ * **y** axis, `y` values along the **x** axis, `width` is the bar thickness.
179
+ */
180
+ orientation?: "v" | "h";
139
181
  color?: string | Color;
140
182
  name?: string;
141
183
  yAxis?: string;
@@ -154,6 +196,7 @@ declare class BarLayer implements Layer {
154
196
  private color;
155
197
  private barWidth;
156
198
  private offset;
199
+ private orientation;
157
200
  private xRef;
158
201
  private yRef;
159
202
  private xBounds;
@@ -260,7 +303,13 @@ declare class CandlestickLayer implements Layer {
260
303
 
261
304
  type RGB = [number, number, number];
262
305
  type ColormapName = "viridis" | "plasma" | "coolwarm" | "grayscale";
263
- /** Returns a `(t in 0..1) => RGB` sampler for the named colormap. */
306
+ /**
307
+ * The raw `256×3` (r,g,b in 0..1) lookup table for a colormap, cached per name.
308
+ * Hot loops (heatmap, colorBy, …) can index it directly — `j = ((clamp(t)*255)|0)*3`
309
+ * — to avoid a per-element closure call and tuple allocation.
310
+ */
311
+ declare function colormapLUT(name?: ColormapName): Float32Array;
312
+ /** Returns a `(t in 0..1) => RGB` sampler for the named colormap (LUT-backed). */
264
313
  declare function colormap(name?: ColormapName): (t: number) => RGB;
265
314
 
266
315
  interface ContourOptions {
@@ -362,6 +411,50 @@ declare class ErrorBarLayer implements Layer {
362
411
  dispose(): void;
363
412
  }
364
413
 
414
+ interface GraphOptions {
415
+ /** Node positions (data space). */
416
+ x: ArrayLike<number>;
417
+ y: ArrayLike<number>;
418
+ /** Edges as index pairs into the node arrays. */
419
+ edges: ReadonlyArray<readonly [number, number]>;
420
+ nodeColor?: string | Color;
421
+ /** Node diameter in CSS pixels. Default 10. */
422
+ nodeSize?: number;
423
+ edgeColor?: string | Color;
424
+ name?: string;
425
+ yAxis?: string;
426
+ }
427
+ /** A node-link graph: edges as line segments, nodes as round points. */
428
+ declare class GraphLayer implements Layer {
429
+ readonly id: string;
430
+ readonly name: string;
431
+ readonly colorCss: string;
432
+ readonly yAxis: string;
433
+ private gl;
434
+ private progs;
435
+ private nodeVao;
436
+ private edgeVao;
437
+ private buffers;
438
+ private edgeUniforms;
439
+ private nodeUniforms;
440
+ private nodeCount;
441
+ private edgeVerts;
442
+ private nodeColor;
443
+ private edgeColor;
444
+ private nodeSize;
445
+ private xRef;
446
+ private yRef;
447
+ private xBounds;
448
+ private yBounds;
449
+ constructor(gl: WebGL2RenderingContext, opts: GraphOptions);
450
+ bounds(): {
451
+ x: Range;
452
+ y: Range;
453
+ } | null;
454
+ draw(state: DrawState): void;
455
+ dispose(): void;
456
+ }
457
+
365
458
  interface HeatmapOptions {
366
459
  /** Row-major grid values, length `cols * rows` (row 0 at the bottom). */
367
460
  values: ArrayLike<number>;
@@ -433,6 +526,59 @@ declare class HexbinLayer implements Layer {
433
526
  dispose(): void;
434
527
  }
435
528
 
529
+ /** Anything `texImage2D` accepts, or a URL string the layer loads itself. */
530
+ type ImageSource = TexImageSource | string;
531
+ interface ImageOptions {
532
+ /** A decoded bitmap/canvas/ImageData, or a URL to load (CORS-enabled). */
533
+ source: ImageSource;
534
+ /** Data-space rectangle the image spans. */
535
+ extent: {
536
+ x: Range;
537
+ y: Range;
538
+ };
539
+ /** Bilinear filtering (default) vs. nearest. */
540
+ smooth?: boolean;
541
+ /** Overall opacity 0..1. Default 1. */
542
+ opacity?: number;
543
+ /** Called after an async (URL) image finishes loading — wire to `plot.requestRender`. */
544
+ onLoad?: () => void;
545
+ name?: string;
546
+ yAxis?: string;
547
+ }
548
+ /**
549
+ * An RGBA image (Bokeh `image_rgba` / `image_url`) drawn as a textured quad over
550
+ * a data-space extent — reuses the heatmap quad path. A `string` source is loaded
551
+ * asynchronously; pass `onLoad` (→ `plot.requestRender`) so the plot redraws once
552
+ * the pixels arrive.
553
+ */
554
+ declare class ImageLayer implements Layer {
555
+ readonly id: string;
556
+ readonly name: string;
557
+ readonly colorCss = "#94a3b8";
558
+ readonly yAxis: string;
559
+ private gl;
560
+ private program;
561
+ private vao;
562
+ private buffer;
563
+ private texture;
564
+ private uniforms;
565
+ private xRef;
566
+ private yRef;
567
+ private ext;
568
+ private opacity;
569
+ private smooth;
570
+ private ready;
571
+ private img;
572
+ constructor(gl: WebGL2RenderingContext, opts: ImageOptions);
573
+ private upload;
574
+ bounds(): {
575
+ x: Range;
576
+ y: Range;
577
+ };
578
+ draw(state: DrawState): void;
579
+ dispose(): void;
580
+ }
581
+
436
582
  /**
437
583
  * Shared hover-picking used by point/series layers (line, scatter, stem).
438
584
  *
@@ -540,6 +686,106 @@ declare class LineLayer implements Layer {
540
686
  dispose(): void;
541
687
  }
542
688
 
689
+ /** One filled polygon: a ring of `x`/`y`, with optional holes. */
690
+ interface Patch {
691
+ x: ArrayLike<number>;
692
+ y: ArrayLike<number>;
693
+ /** Vertex indices where each hole ring starts (mapbox-earcut convention). */
694
+ holes?: number[];
695
+ /** Explicit fill color (overrides the layer default / colormap). */
696
+ color?: string | Color;
697
+ /** Value used to color this patch via the layer `colormap` (choropleth). */
698
+ value?: number;
699
+ }
700
+ interface PatchesOptions {
701
+ patches: Patch[];
702
+ /** Default fill for patches without their own `color`/`value`. */
703
+ color?: string | Color;
704
+ /** Color patches by `value` through this colormap (choropleth). */
705
+ colormap?: ColormapName;
706
+ /** Value range mapped to [0,1] for the colormap. Defaults to the data min/max. */
707
+ domain?: Range;
708
+ /** Fill opacity, 0..1. Default 1. */
709
+ opacity?: number;
710
+ name?: string;
711
+ yAxis?: string;
712
+ }
713
+ /**
714
+ * Filled polygons (Bokeh `patches`). Each ring is triangulated once on the CPU
715
+ * with ear-clipping (holes supported), then rendered as a static per-vertex-color
716
+ * triangle soup — only the transform uniforms change per frame.
717
+ */
718
+ declare class PatchesLayer implements Layer {
719
+ readonly id: string;
720
+ readonly name: string;
721
+ readonly colorCss: string;
722
+ readonly yAxis: string;
723
+ private gl;
724
+ private program;
725
+ private vao;
726
+ private buffers;
727
+ private uniforms;
728
+ private vertexCount;
729
+ private xRef;
730
+ private yRef;
731
+ private xBounds;
732
+ private yBounds;
733
+ constructor(gl: WebGL2RenderingContext, opts: PatchesOptions);
734
+ bounds(): {
735
+ x: Range;
736
+ y: Range;
737
+ } | null;
738
+ draw(state: DrawState): void;
739
+ dispose(): void;
740
+ }
741
+
742
+ interface PieOptions {
743
+ /** Slice magnitudes (need not sum to 1 — they are normalized). */
744
+ values: ArrayLike<number>;
745
+ /** Explicit per-slice colors; falls back to `colormap`, then a default palette. */
746
+ colors?: (string | Color)[];
747
+ /** Color slices by index through this colormap instead of the palette. */
748
+ colormap?: ColormapName;
749
+ /** Center in data space. Default `[0, 0]`. */
750
+ center?: [number, number];
751
+ /** Outer radius in data units. Default `1`. */
752
+ radius?: number;
753
+ /** Inner radius (> 0 makes a donut). Default `0`. */
754
+ innerRadius?: number;
755
+ /** Angle of the first slice edge, radians. Default `Math.PI / 2` (12 o'clock). */
756
+ startAngle?: number;
757
+ name?: string;
758
+ yAxis?: string;
759
+ }
760
+ /**
761
+ * A pie / donut chart drawn as a per-vertex-color triangle soup (wedges as fans,
762
+ * or quad strips when a donut). Reuses the shared solid-fill program. Slices sweep
763
+ * clockwise from `startAngle`. Set the plot's `equalAspect` so it stays circular.
764
+ */
765
+ declare class PieLayer implements Layer {
766
+ readonly id: string;
767
+ readonly name: string;
768
+ readonly colorCss: string;
769
+ readonly yAxis: string;
770
+ private gl;
771
+ private program;
772
+ private vao;
773
+ private buffers;
774
+ private uniforms;
775
+ private vertexCount;
776
+ private xRef;
777
+ private yRef;
778
+ private xBounds;
779
+ private yBounds;
780
+ constructor(gl: WebGL2RenderingContext, opts: PieOptions);
781
+ bounds(): {
782
+ x: Range;
783
+ y: Range;
784
+ } | null;
785
+ draw(state: DrawState): void;
786
+ dispose(): void;
787
+ }
788
+
543
789
  interface QuiverOptions {
544
790
  /** Arrow anchor positions (data space). */
545
791
  x: ArrayLike<number>;
@@ -594,12 +840,16 @@ declare class QuiverLayer implements Layer {
594
840
  dispose(): void;
595
841
  }
596
842
 
843
+ /** Marker glyph shape for a scatter series. */
844
+ type MarkerShape = "circle" | "square" | "triangle" | "diamond" | "cross" | "plus";
597
845
  interface ScatterOptions {
598
846
  x: ArrayLike<number>;
599
847
  y: ArrayLike<number>;
600
848
  color?: string | Color;
601
849
  /** Marker diameter in CSS pixels. */
602
850
  size?: number;
851
+ /** Marker glyph. Default `"circle"`. */
852
+ marker?: MarkerShape;
603
853
  name?: string;
604
854
  yAxis?: string;
605
855
  /**
@@ -628,6 +878,7 @@ declare class ScatterLayer implements Layer {
628
878
  private uniforms;
629
879
  private count;
630
880
  private size;
881
+ private marker;
631
882
  private color;
632
883
  private useVertexColor;
633
884
  private labels?;
@@ -748,8 +999,26 @@ declare class TimeScale implements Scale {
748
999
  ticks(target?: number): Tick[];
749
1000
  formatTick(value: number): string;
750
1001
  }
751
- type ScaleType = "linear" | "log" | "time";
752
- declare function makeScale(type: ScaleType, domain?: Range): Scale;
1002
+ /**
1003
+ * A categorical (factor) axis. Internally it is **linear over a band domain**
1004
+ * `[-0.5, n-0.5]`, so factor `i` sits at the band centre and `norm(i)` equals the
1005
+ * ordinary linear projection — the GPU transform needs no special handling, and a
1006
+ * layer plotting at integer indices lands on band centres automatically.
1007
+ * "Categorical-ness" lives only in the ticks/labels (one per factor).
1008
+ */
1009
+ declare class CategoricalScale implements Scale {
1010
+ readonly type = "categorical";
1011
+ readonly log = false;
1012
+ factors: string[];
1013
+ domain: Range;
1014
+ constructor(factors?: string[]);
1015
+ norm(value: number): number;
1016
+ invert(t: number): number;
1017
+ ticks(): Tick[];
1018
+ formatTick(value: number): string;
1019
+ }
1020
+ type ScaleType = "linear" | "log" | "time" | "categorical";
1021
+ declare function makeScale(type: ScaleType, domain?: Range, factors?: string[]): Scale;
753
1022
 
754
1023
  /** Pixel geometry of the plot, in CSS pixels. The plot region excludes margins. */
755
1024
  interface Layout {
@@ -771,20 +1040,158 @@ interface Theme {
771
1040
  }
772
1041
  declare const lightTheme: Theme;
773
1042
  declare const darkTheme: Theme;
1043
+ /** Concrete axis styling, resolved from an {@link AxisConfig} against a {@link Theme}. */
1044
+ interface ResolvedAxisStyle {
1045
+ showAxisLine: boolean;
1046
+ axisLineColor: string;
1047
+ axisLineWidth: number;
1048
+ showTicks: boolean;
1049
+ tickColor: string;
1050
+ tickLength: number;
1051
+ tickMinorLength: number;
1052
+ tickWidth: number;
1053
+ labelColor: string;
1054
+ labelFont: string;
1055
+ labelRotation: number;
1056
+ labelStandoff: number;
1057
+ titleColor: string;
1058
+ titleFont: string;
1059
+ showGrid: boolean;
1060
+ gridColor: string;
1061
+ gridMinorColor: string;
1062
+ gridWidth: number;
1063
+ gridDash: number[];
1064
+ }
1065
+ /**
1066
+ * Fold an {@link AxisConfig}'s optional style fields onto the theme defaults.
1067
+ * Colored fields fall back to `colorOverride` (a secondary y-axis's `color`) before
1068
+ * the theme, so an unstyled colored axis still tints its line/ticks/labels/title.
1069
+ * With an empty config this reproduces the pre-styling look exactly.
1070
+ */
1071
+ declare function resolveAxisStyle(cfg: AxisConfig, theme: Theme, colorOverride?: string): ResolvedAxisStyle;
1072
+ interface PlotTitleOptions {
1073
+ text: string;
1074
+ /** CSS `font` shorthand. Default `"600 15px system-ui, ..."`. */
1075
+ font?: string;
1076
+ color?: string;
1077
+ align?: "left" | "center" | "right";
1078
+ }
774
1079
 
775
1080
  interface AxisScaleOptions {
776
1081
  type?: ScaleType;
777
1082
  /** Fixed domain. If omitted, the axis autoscales to the data. */
778
1083
  domain?: Range;
1084
+ /** Factor labels for a `"categorical"` axis (fixes the domain to the bands). */
1085
+ factors?: string[];
1086
+ }
1087
+ /** Legend placement + styling. `legend: true` uses all defaults. */
1088
+ interface LegendOptions {
1089
+ /** Corner within the plot region. Default `"top-right"`. */
1090
+ position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
1091
+ /** Stack entries vertically (default) or in a row. */
1092
+ orientation?: "vertical" | "horizontal";
1093
+ background?: string;
1094
+ border?: string;
1095
+ textColor?: string;
1096
+ font?: string;
779
1097
  }
780
1098
  interface YAxisOptions extends AxisConfig {
781
1099
  type?: ScaleType;
782
1100
  domain?: Range;
1101
+ /** Factor labels for a `"categorical"` axis. */
1102
+ factors?: string[];
783
1103
  /** Which side to draw the axis on. Default `"right"` for secondary axes. */
784
1104
  side?: "left" | "right";
785
1105
  /** Axis + label color (secondary axes often match their series). */
786
1106
  color?: string;
787
1107
  }
1108
+ /** One series in a grouped/stacked bar chart. */
1109
+ interface BarSeries {
1110
+ /** Value per category (parallel to the shared `x` positions). */
1111
+ y: ArrayLike<number>;
1112
+ color?: string;
1113
+ name?: string;
1114
+ }
1115
+ /** Options for {@link Plot.addGroupedBars} — one cluster of bars per category. */
1116
+ interface GroupedBarOptions {
1117
+ /** Category positions (e.g. `0..n-1` for a categorical axis). */
1118
+ x: ArrayLike<number>;
1119
+ series: BarSeries[];
1120
+ /** Total width of one group (all its bars) in data units. Default 0.8. */
1121
+ groupWidth?: number;
1122
+ /** Fractional gap between bars within a group, 0..1. Default 0.1. */
1123
+ gap?: number;
1124
+ /** `"v"` vertical (default) or `"h"` horizontal bars. */
1125
+ orientation?: "v" | "h";
1126
+ yAxis?: string;
1127
+ }
1128
+ /** Options for {@link Plot.addStackedBars} — series stacked on top of each other. */
1129
+ interface StackedBarOptions {
1130
+ /** Category positions (e.g. `0..n-1` for a categorical axis). */
1131
+ x: ArrayLike<number>;
1132
+ series: BarSeries[];
1133
+ /** Bar width in data units. Defaults to 80% of the median spacing. */
1134
+ width?: number;
1135
+ /** `"v"` vertical (default) or `"h"` horizontal bars. */
1136
+ orientation?: "v" | "h";
1137
+ yAxis?: string;
1138
+ }
1139
+ /** One series in a stacked area chart. */
1140
+ interface AreaSeries {
1141
+ y: ArrayLike<number>;
1142
+ color?: string;
1143
+ name?: string;
1144
+ }
1145
+ /** Options for {@link Plot.addStackedArea}. */
1146
+ interface StackedAreaOptions {
1147
+ x: ArrayLike<number>;
1148
+ series: AreaSeries[];
1149
+ yAxis?: string;
1150
+ }
1151
+ /** Options for {@link Plot.addGraph}. Positions are optional — omit them (give `nodes`) to auto-lay-out. */
1152
+ interface GraphInput extends Omit<GraphOptions, "x" | "y"> {
1153
+ x?: ArrayLike<number>;
1154
+ y?: ArrayLike<number>;
1155
+ /** Node count when `x`/`y` are omitted (else inferred from the max edge index). */
1156
+ nodes?: number;
1157
+ }
1158
+ /**
1159
+ * A Canvas2D overlay marker drawn above the data, projected through the scales:
1160
+ * a full-width/height guide line (`span`), a shaded range (`band`), a rectangle
1161
+ * (`box`), or text (`label`). `yAxis` targets a secondary axis where relevant.
1162
+ */
1163
+ type Annotation = {
1164
+ type: "span";
1165
+ dim: Dim;
1166
+ value: number;
1167
+ color?: string;
1168
+ width?: number;
1169
+ dash?: number[];
1170
+ yAxis?: string;
1171
+ } | {
1172
+ type: "band";
1173
+ dim: Dim;
1174
+ from: number;
1175
+ to: number;
1176
+ color?: string;
1177
+ yAxis?: string;
1178
+ } | {
1179
+ type: "box";
1180
+ x: Range;
1181
+ y: Range;
1182
+ color?: string;
1183
+ border?: string;
1184
+ yAxis?: string;
1185
+ } | {
1186
+ type: "label";
1187
+ x: number;
1188
+ y: number;
1189
+ text: string;
1190
+ color?: string;
1191
+ font?: string;
1192
+ align?: "left" | "center" | "right";
1193
+ yAxis?: string;
1194
+ };
788
1195
  /** One line of the hover tooltip header, produced by {@link PlotOptions.hoverReadout}. */
789
1196
  interface HoverReadoutRow {
790
1197
  label: string;
@@ -800,6 +1207,14 @@ interface PlotOptions {
800
1207
  y?: AxisConfig;
801
1208
  };
802
1209
  theme?: "light" | "dark" | Theme;
1210
+ /** Fill color for the plot region (inside the margins). Default transparent. */
1211
+ background?: string;
1212
+ /** Fill color for the whole canvas incl. margins. Default transparent. */
1213
+ border?: string;
1214
+ /** Plot title, drawn in a reserved strip above the plot. */
1215
+ title?: string | PlotTitleOptions;
1216
+ /** Show a legend of named series. `true` uses defaults; pass an object to place/style it. */
1217
+ legend?: boolean | LegendOptions;
803
1218
  margin?: Partial<Layout["margin"]>;
804
1219
  /** Enable wheel-zoom and drag interaction. Default true. */
805
1220
  interactive?: boolean;
@@ -892,6 +1307,12 @@ declare class Plot {
892
1307
  /** A point clicked to pin its details, until another click clears it. */
893
1308
  private selected;
894
1309
  private infoBox;
1310
+ private annotations;
1311
+ private bgFill?;
1312
+ private borderFill?;
1313
+ private title;
1314
+ private legend;
1315
+ private legendDiv;
895
1316
  constructor(container: HTMLElement, options?: PlotOptions);
896
1317
  private makeCanvas;
897
1318
  /** Margins grow to make room for extra y axes on each side. */
@@ -919,6 +1340,16 @@ declare class Plot {
919
1340
  addLine(opts: LineOptions): LineLayer;
920
1341
  addScatter(opts: ScatterOptions): ScatterLayer;
921
1342
  addBar(opts: BarOptions): BarLayer;
1343
+ /**
1344
+ * Grouped (clustered) bars: one {@link BarLayer} per series, each shifted within
1345
+ * its category group so the bars sit side by side. Returns the layers in order.
1346
+ */
1347
+ addGroupedBars(opts: GroupedBarOptions): BarLayer[];
1348
+ /**
1349
+ * Stacked bars: each series is drawn from the running cumulative total of the
1350
+ * ones before it, so they stack. Returns the layers bottom-to-top.
1351
+ */
1352
+ addStackedBars(opts: StackedBarOptions): BarLayer[];
922
1353
  addArea(opts: AreaOptions): AreaLayer;
923
1354
  addHeatmap(opts: HeatmapOptions): HeatmapLayer;
924
1355
  addBox(opts: BoxOptions): BoxLayer;
@@ -928,6 +1359,29 @@ declare class Plot {
928
1359
  addStem(opts: StemOptions): StemLayer;
929
1360
  addQuiver(opts: QuiverOptions): QuiverLayer;
930
1361
  addCandlestick(opts: CandlestickOptions): CandlestickLayer;
1362
+ /** Filled polygons (choropleth-capable). Rings are triangulated with earcut. */
1363
+ addPatches(opts: PatchesOptions): PatchesLayer;
1364
+ /** A pie / donut chart. Set `equalAspect: true` on the plot so it stays circular. */
1365
+ addPie(opts: PieOptions): PieLayer;
1366
+ /** An RGBA image / URL drawn over a data-space extent. URLs redraw on load. */
1367
+ addImage(opts: ImageOptions): ImageLayer;
1368
+ /**
1369
+ * A node-link graph. Provide node `x`/`y`, or omit them (with `nodes`, or let the
1370
+ * count be inferred from the edges) to auto-place with a force-directed layout.
1371
+ */
1372
+ addGraph(opts: GraphInput): GraphLayer;
1373
+ /**
1374
+ * Stacked area: each series is filled from the running cumulative total of the
1375
+ * ones before it. Returns the layers bottom-to-top.
1376
+ */
1377
+ addStackedArea(opts: StackedAreaOptions): AreaLayer[];
1378
+ /**
1379
+ * Add a Canvas2D annotation (span / band / box / label) drawn above the data.
1380
+ * Returns a disposer that removes just this annotation.
1381
+ */
1382
+ addAnnotation(a: Annotation): () => void;
1383
+ /** Remove all annotations. */
1384
+ clearAnnotations(): void;
931
1385
  /** Compute an STFT of `signal` and render it as a heatmap (time × frequency). */
932
1386
  addHeatmapSpectrogram(signal: ArrayLike<number>, opts?: {
933
1387
  fftSize?: number;
@@ -967,6 +1421,12 @@ declare class Plot {
967
1421
  requestRender(): void;
968
1422
  private primaryY;
969
1423
  render(): void;
1424
+ /** Named series that can appear in the legend: any layer exposing name + colorCss. */
1425
+ private legendEntries;
1426
+ /** Rebuild and position the legend overlay (or hide it). */
1427
+ private updateLegend;
1428
+ /** Draw all annotations, projected through the scales and clipped to the region. */
1429
+ private renderAnnotations;
970
1430
  private renderHover;
971
1431
  private updateTooltip;
972
1432
  private updateCursor;
@@ -1027,6 +1487,25 @@ declare function createToolbar(container: HTMLElement, host: ToolbarHost, dark:
1027
1487
  destroy: () => void;
1028
1488
  };
1029
1489
 
1490
+ /**
1491
+ * A tiny deterministic force-directed layout (Fruchterman–Reingold style). Nodes
1492
+ * seed on a unit circle (no RNG — pure and unit-testable), then relax under
1493
+ * all-pairs repulsion + per-edge attraction + a gentle pull to the center, with
1494
+ * temperature cooling. Returns node positions in roughly a unit box around 0.
1495
+ */
1496
+ interface ForceLayoutOptions {
1497
+ /** Relaxation steps. Default 300. */
1498
+ iterations?: number;
1499
+ /** Layout area; the ideal edge length is `sqrt(area / n)`. Default 1. */
1500
+ area?: number;
1501
+ /** Pull toward the origin each step. Default 0.05. */
1502
+ gravity?: number;
1503
+ }
1504
+ declare function forceLayout(nodeCount: number, edges: ReadonlyArray<readonly [number, number]>, opts?: ForceLayoutOptions): {
1505
+ x: Float64Array;
1506
+ y: Float64Array;
1507
+ };
1508
+
1030
1509
  interface PolarOptions {
1031
1510
  theme?: "light" | "dark" | Theme;
1032
1511
  /** Angle unit of input theta values. Default `"rad"`. */
@@ -1148,10 +1627,188 @@ interface Bounds3 {
1148
1627
  y: Range;
1149
1628
  z: Range;
1150
1629
  }
1630
+ /** A colormapped layer's scale, surfaced to {@link Plot3D} for a colorbar. */
1631
+ interface ColorInfo {
1632
+ colormap: ColormapName;
1633
+ domain: Range;
1634
+ label?: string;
1635
+ }
1151
1636
  /** A drawable in the 3D scene. Positions are in world space; Plot3D supplies the MVP. */
1152
1637
  interface Layer3D {
1153
1638
  readonly id: string;
1639
+ /** Series name for the legend (optional). */
1640
+ readonly name?: string;
1641
+ /** A solid CSS color for the legend swatch (solid-colored layers only). */
1642
+ readonly colorCss?: string;
1643
+ bounds3(): Bounds3 | null;
1644
+ /** Colormap + value range for a colorbar, if this layer is colormapped. */
1645
+ colorInfo?(): ColorInfo | null;
1646
+ /**
1647
+ * Data-space points for hover picking (xyz triples), with an optional per-point
1648
+ * tooltip label builder. Null if the layer isn't pickable.
1649
+ */
1650
+ pickData?(): {
1651
+ positions: Float32Array;
1652
+ label?: (i: number) => string;
1653
+ } | null;
1654
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1655
+ dispose(): void;
1656
+ }
1657
+
1658
+ interface Bar3DOptions {
1659
+ /** Grid x positions (world). */
1660
+ x: ArrayLike<number>;
1661
+ /** Grid z positions (world). */
1662
+ z: ArrayLike<number>;
1663
+ /** Bar heights. */
1664
+ y: ArrayLike<number>;
1665
+ /** Footprint (world units). Defaults to ~0.7× the median grid spacing. */
1666
+ width?: number;
1667
+ color?: string | Color;
1668
+ /** Color bars via a colormap (over `values`, default the heights). */
1669
+ colorBy?: {
1670
+ values?: ArrayLike<number>;
1671
+ colormap?: ColormapName;
1672
+ domain?: Range;
1673
+ };
1674
+ name?: string;
1675
+ }
1676
+ /** 3D bars (columns) on an x/z grid, lit like the surface and optionally colormapped. */
1677
+ declare class Bar3DLayer implements Layer3D {
1678
+ readonly id: string;
1679
+ readonly name?: string;
1680
+ readonly colorCss?: string;
1681
+ private gl;
1682
+ private program;
1683
+ private vao;
1684
+ private buffers;
1685
+ private uniforms;
1686
+ private count;
1687
+ private width;
1688
+ private b3;
1689
+ private cInfo;
1690
+ private positions;
1691
+ private lightDir;
1692
+ private ambient;
1693
+ constructor(gl: WebGL2RenderingContext, opts: Bar3DOptions);
1154
1694
  bounds3(): Bounds3 | null;
1695
+ colorInfo(): ColorInfo | null;
1696
+ pickData(): {
1697
+ positions: Float32Array<ArrayBufferLike>;
1698
+ } | null;
1699
+ /** Set the light direction (world space) and ambient term (0..1). */
1700
+ setLight(dir: [number, number, number], ambient: number): void;
1701
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1702
+ dispose(): void;
1703
+ }
1704
+
1705
+ interface Contour3DOptions {
1706
+ /** Row-major height grid, length `cols * rows`. */
1707
+ values: ArrayLike<number>;
1708
+ cols: number;
1709
+ rows: number;
1710
+ /** World footprint. Defaults to unit indices. */
1711
+ extentX?: Range;
1712
+ extentZ?: Range;
1713
+ /** Iso levels: an explicit list, or a count of evenly-spaced levels. Default 10. */
1714
+ levels?: number[] | number;
1715
+ /** Single line color; if omitted, levels are colored by a colormap. */
1716
+ color?: string | Color;
1717
+ colormap?: ColormapName;
1718
+ name?: string;
1719
+ }
1720
+ /**
1721
+ * 3D contour: iso-height lines of a grid, each drawn at its own level height
1722
+ * (`y = level`) so they stack into a floating topographic map. Marching squares
1723
+ * on the CPU, per-vertex colored by level.
1724
+ */
1725
+ declare class Contour3DLayer implements Layer3D {
1726
+ readonly id: string;
1727
+ readonly name?: string;
1728
+ private gl;
1729
+ private program;
1730
+ private vao;
1731
+ private buffer;
1732
+ private uniforms;
1733
+ private vertCount;
1734
+ private b3;
1735
+ private cInfo;
1736
+ constructor(gl: WebGL2RenderingContext, opts: Contour3DOptions);
1737
+ bounds3(): Bounds3 | null;
1738
+ colorInfo(): ColorInfo | null;
1739
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1740
+ dispose(): void;
1741
+ }
1742
+
1743
+ interface IsosurfaceOptions {
1744
+ /** Scalar volume, length `nx*ny*nz`, indexed `x + y*nx + z*nx*ny`. */
1745
+ values: ArrayLike<number>;
1746
+ dims: [number, number, number];
1747
+ /** The iso value to extract the surface at. */
1748
+ isoLevel: number;
1749
+ /** World extent of the volume. Defaults to unit indices. */
1750
+ extent?: {
1751
+ x: Range;
1752
+ y: Range;
1753
+ z: Range;
1754
+ };
1755
+ color?: string | Color;
1756
+ /** Fill opacity 0..1. Default 1. */
1757
+ opacity?: number;
1758
+ name?: string;
1759
+ }
1760
+ /** A marching-cubes isosurface of a 3D scalar volume, lit and solid-colored. */
1761
+ declare class IsosurfaceLayer implements Layer3D {
1762
+ readonly id: string;
1763
+ readonly name?: string;
1764
+ readonly colorCss: string;
1765
+ private gl;
1766
+ private program;
1767
+ private vao;
1768
+ private buffer;
1769
+ private uniforms;
1770
+ private vertCount;
1771
+ private color;
1772
+ private opacity;
1773
+ private b3;
1774
+ private lightDir;
1775
+ private ambient;
1776
+ constructor(gl: WebGL2RenderingContext, opts: IsosurfaceOptions);
1777
+ bounds3(): Bounds3 | null;
1778
+ /** Set the light direction (world space) and ambient term (0..1). */
1779
+ setLight(dir: [number, number, number], ambient: number): void;
1780
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1781
+ dispose(): void;
1782
+ }
1783
+
1784
+ interface Line3DOptions {
1785
+ x: ArrayLike<number>;
1786
+ y: ArrayLike<number>;
1787
+ z: ArrayLike<number>;
1788
+ color?: string | Color;
1789
+ name?: string;
1790
+ }
1791
+ /** A 3D polyline / path (`GL_LINE_STRIP`). */
1792
+ declare class Line3DLayer implements Layer3D {
1793
+ readonly id: string;
1794
+ readonly name?: string;
1795
+ readonly colorCss: string;
1796
+ private gl;
1797
+ private program;
1798
+ private vao;
1799
+ private buffer;
1800
+ private uniforms;
1801
+ private count;
1802
+ private color;
1803
+ private b3;
1804
+ private positions;
1805
+ constructor(gl: WebGL2RenderingContext, opts: Line3DOptions);
1806
+ bounds3(): Bounds3 | null;
1807
+ pickData(): {
1808
+ positions: Float32Array<ArrayBufferLike>;
1809
+ } | null;
1810
+ /** Stream a new path. Call `plot.refresh()` afterwards to re-fit + redraw. */
1811
+ setData(x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number>): void;
1155
1812
  draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1156
1813
  dispose(): void;
1157
1814
  }
@@ -1161,15 +1818,24 @@ interface PointCloudOptions {
1161
1818
  y: ArrayLike<number>;
1162
1819
  z: ArrayLike<number>;
1163
1820
  color?: string | Color;
1821
+ /** Uniform point diameter (px) when `sizes` is omitted. Default 4. */
1164
1822
  size?: number;
1823
+ /** Per-point diameter (px); overrides `size` where > 0. */
1824
+ sizes?: ArrayLike<number>;
1165
1825
  colorBy?: {
1166
1826
  values: ArrayLike<number>;
1167
1827
  colormap?: ColormapName;
1168
1828
  domain?: Range;
1169
1829
  };
1830
+ /** Per-point tooltip text (parallel to x/y/z). */
1831
+ labels?: ArrayLike<string>;
1832
+ /** Series name (legend / colorbar label). */
1833
+ name?: string;
1170
1834
  }
1171
1835
  declare class PointCloudLayer implements Layer3D {
1172
1836
  readonly id: string;
1837
+ readonly name?: string;
1838
+ readonly colorCss?: string;
1173
1839
  private gl;
1174
1840
  private program;
1175
1841
  private vao;
@@ -1178,8 +1844,66 @@ declare class PointCloudLayer implements Layer3D {
1178
1844
  private count;
1179
1845
  private size;
1180
1846
  private b3;
1847
+ private cInfo;
1848
+ private positions;
1849
+ private labels?;
1850
+ /** Interleaved pos(3)+color(3)+size(1); positions are streamed in place. */
1851
+ private data;
1181
1852
  constructor(gl: WebGL2RenderingContext, opts: PointCloudOptions);
1853
+ private updateBounds;
1854
+ /** Stream new point positions (same count keeps colors/sizes). Call `plot.refresh()` after. */
1855
+ setData(x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number>): void;
1182
1856
  bounds3(): Bounds3 | null;
1857
+ colorInfo(): ColorInfo | null;
1858
+ pickData(): {
1859
+ positions: Float32Array<ArrayBufferLike>;
1860
+ label: ((i: number) => string) | undefined;
1861
+ } | null;
1862
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1863
+ dispose(): void;
1864
+ }
1865
+
1866
+ interface Quiver3DOptions {
1867
+ /** Arrow base points. */
1868
+ x: ArrayLike<number>;
1869
+ y: ArrayLike<number>;
1870
+ z: ArrayLike<number>;
1871
+ /** Vector components. */
1872
+ u: ArrayLike<number>;
1873
+ v: ArrayLike<number>;
1874
+ w: ArrayLike<number>;
1875
+ /** Multiply the vectors before drawing. Default 1. */
1876
+ scale?: number;
1877
+ color?: string | Color;
1878
+ /** Color arrows by magnitude via a colormap. */
1879
+ colorBy?: {
1880
+ colormap?: ColormapName;
1881
+ domain?: Range;
1882
+ };
1883
+ /** Arrowhead length as a fraction of the arrow. Default 0.28. */
1884
+ headSize?: number;
1885
+ name?: string;
1886
+ }
1887
+ /** A 3D vector field: each arrow is a shaft + a 4-wing arrowhead, drawn as lines. */
1888
+ declare class Quiver3DLayer implements Layer3D {
1889
+ readonly id: string;
1890
+ readonly name?: string;
1891
+ readonly colorCss?: string;
1892
+ private gl;
1893
+ private program;
1894
+ private vao;
1895
+ private buffer;
1896
+ private uniforms;
1897
+ private vertCount;
1898
+ private b3;
1899
+ private cInfo;
1900
+ private positions;
1901
+ constructor(gl: WebGL2RenderingContext, opts: Quiver3DOptions);
1902
+ bounds3(): Bounds3 | null;
1903
+ colorInfo(): ColorInfo | null;
1904
+ pickData(): {
1905
+ positions: Float32Array<ArrayBufferLike>;
1906
+ } | null;
1183
1907
  draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1184
1908
  dispose(): void;
1185
1909
  }
@@ -1193,9 +1917,14 @@ interface SurfaceOptions {
1193
1917
  extentX?: Range;
1194
1918
  extentZ?: Range;
1195
1919
  colormap?: ColormapName;
1920
+ /** Series name (colorbar label / legend). */
1921
+ name?: string;
1922
+ /** Render the grid as a wireframe (lines) instead of a lit filled surface. */
1923
+ wireframe?: boolean;
1196
1924
  }
1197
1925
  declare class SurfaceLayer implements Layer3D {
1198
1926
  readonly id: string;
1927
+ readonly name?: string;
1199
1928
  private gl;
1200
1929
  private program;
1201
1930
  private vao;
@@ -1203,16 +1932,67 @@ declare class SurfaceLayer implements Layer3D {
1203
1932
  private uniforms;
1204
1933
  private vertexCount;
1205
1934
  private b3;
1935
+ private cmapName;
1936
+ private vDomain;
1937
+ private wireframe;
1206
1938
  private lightDir;
1207
1939
  private ambient;
1208
1940
  constructor(gl: WebGL2RenderingContext, opts: SurfaceOptions);
1209
1941
  bounds3(): Bounds3;
1942
+ colorInfo(): ColorInfo;
1210
1943
  /** Set the light direction (world space) and ambient term (0..1). */
1211
1944
  setLight(dir: [number, number, number], ambient: number): void;
1212
1945
  draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1213
1946
  dispose(): void;
1214
1947
  }
1215
1948
 
1949
+ interface VolumeOptions {
1950
+ /** Scalar volume, length `nx*ny*nz`, indexed `x + y*nx + z*nx*ny`. */
1951
+ values: ArrayLike<number>;
1952
+ dims: [number, number, number];
1953
+ /** World extent of the volume. Defaults to unit indices. */
1954
+ extent?: {
1955
+ x: Range;
1956
+ y: Range;
1957
+ z: Range;
1958
+ };
1959
+ colormap?: ColormapName;
1960
+ /** Value range mapped to the colormap + opacity. Defaults to the data min/max. */
1961
+ domain?: Range;
1962
+ /** Overall opacity multiplier. Default 1. */
1963
+ density?: number;
1964
+ name?: string;
1965
+ }
1966
+ /**
1967
+ * Direct volume rendering: GPU raymarching through a 3D texture with front-to-back
1968
+ * alpha compositing and a colormap transfer function. Draws the volume's bounding
1969
+ * box (back faces) and integrates each ray across the box interior.
1970
+ */
1971
+ declare class VolumeLayer implements Layer3D {
1972
+ readonly id: string;
1973
+ readonly name?: string;
1974
+ private gl;
1975
+ private program;
1976
+ private vao;
1977
+ private buffer;
1978
+ private tex;
1979
+ private lut;
1980
+ private uniforms;
1981
+ private b3;
1982
+ private ext;
1983
+ private density;
1984
+ private cmapName;
1985
+ private vDomain;
1986
+ private camLocal;
1987
+ constructor(gl: WebGL2RenderingContext, opts: VolumeOptions);
1988
+ bounds3(): Bounds3;
1989
+ colorInfo(): ColorInfo;
1990
+ /** Set the camera position in world space; converted to the volume's [0,1] local space. */
1991
+ setCamera(worldEye: [number, number, number]): void;
1992
+ draw(gl: WebGL2RenderingContext, mvp: Mat4): void;
1993
+ dispose(): void;
1994
+ }
1995
+
1216
1996
  interface Plot3DOptions {
1217
1997
  background?: [number, number, number, number];
1218
1998
  azimuth?: number;
@@ -1226,6 +2006,22 @@ interface Plot3DOptions {
1226
2006
  };
1227
2007
  /** Render a small on-canvas panel with light-angle + ambient sliders. */
1228
2008
  lightControls?: boolean;
2009
+ /** Plot title, drawn top-center. */
2010
+ title?: string;
2011
+ /** Show a legend of named solid-colored layers. Default false. */
2012
+ legend?: boolean;
2013
+ /** Show a colorbar for the first colormapped layer. Default true when one exists. */
2014
+ colorbar?: boolean | {
2015
+ label?: string;
2016
+ };
2017
+ /** Hover tooltip on the nearest pickable point. Default true. */
2018
+ hover?: boolean;
2019
+ /** Show a reset-view (home) button. Default true. */
2020
+ resetButton?: boolean;
2021
+ /** Draw grid lines on the back walls of the cube. Default true. */
2022
+ gridPlanes?: boolean;
2023
+ /** Auto-orbit the camera: `true` for a default speed, or radians/frame. Default off. */
2024
+ autoRotate?: boolean | number;
1229
2025
  }
1230
2026
  /** A 3D scatter/surface plot with an orbit camera, axis ticks, and lighting. */
1231
2027
  declare class Plot3D {
@@ -1253,14 +2049,51 @@ declare class Plot3D {
1253
2049
  private tickBuf;
1254
2050
  private tickCount;
1255
2051
  private labels;
2052
+ /** Tick positions in cube space [-1,1], per axis, for the grid planes. */
2053
+ private tickCube;
2054
+ private gridPlanes;
2055
+ private gridVao;
2056
+ private gridBuf;
2057
+ /** Normalize params (world→cube: `cube = s*world + t`), for the volume camera. */
2058
+ private norm;
2059
+ /** Auto-orbit speed (rad/frame); 0 = off. Paused while the pointer is down. */
2060
+ private autoRotateSpeed;
2061
+ private rotating;
2062
+ private interacting;
1256
2063
  private lightAz;
1257
2064
  private lightEl;
1258
2065
  private ambient;
1259
2066
  private controlsEl;
2067
+ private title?;
2068
+ private showLegend;
2069
+ private colorbarOpt;
2070
+ private legendDiv;
2071
+ private colorbarDiv;
2072
+ private tooltip;
2073
+ private resetBtn;
2074
+ private hoverEnabled;
2075
+ /** Screen position (device px) of the picked point, for the highlight ring. */
2076
+ private hoverHit;
2077
+ /** Initial camera, restored by {@link resetView}. */
2078
+ private initialAz;
2079
+ private initialEl;
2080
+ private initialDist;
1260
2081
  constructor(container: HTMLElement, options?: Plot3DOptions);
1261
2082
  private bindLineVao;
1262
2083
  addSurface(opts: SurfaceOptions): SurfaceLayer;
1263
2084
  addPointCloud(opts: PointCloudOptions): PointCloudLayer;
2085
+ /** A 3D polyline / path. */
2086
+ addLine3D(opts: Line3DOptions): Line3DLayer;
2087
+ /** 3D bars (columns) on an x/z grid, lit and optionally colormapped. */
2088
+ addBar3D(opts: Bar3DOptions): Bar3DLayer;
2089
+ /** A 3D vector field (arrows), optionally colored by magnitude. */
2090
+ addQuiver3D(opts: Quiver3DOptions): Quiver3DLayer;
2091
+ /** 3D iso-height contour lines of a grid, stacked at their level heights. */
2092
+ addContour3D(opts: Contour3DOptions): Contour3DLayer;
2093
+ /** A marching-cubes isosurface of a 3D scalar volume (lit, solid-colored). */
2094
+ addIsosurface(opts: IsosurfaceOptions): IsosurfaceLayer;
2095
+ /** Direct volume rendering (GPU raymarch) of a 3D scalar field. */
2096
+ addVolume(opts: VolumeOptions): VolumeLayer;
1264
2097
  /** Update the light direction (azimuth/elevation, radians) and ambient (0..1). */
1265
2098
  setLight(params: {
1266
2099
  azimuth?: number;
@@ -1268,6 +2101,18 @@ declare class Plot3D {
1268
2101
  ambient?: number;
1269
2102
  }): void;
1270
2103
  private lightDir;
2104
+ /** Auto-orbit the camera. `true` = default speed, number = radians/frame, `false`/0 stops. */
2105
+ setAutoRotate(speed: number | boolean): void;
2106
+ /** Restore the initial camera orientation and zoom. */
2107
+ resetView(): void;
2108
+ /** Nearest pickable point to the cursor. Screen coords are device px. */
2109
+ private pick;
2110
+ /** Show/hide the hover tooltip + highlight ring for the point under the cursor. */
2111
+ private updateHover;
2112
+ /** Remove a layer, re-fit, and redraw. */
2113
+ removeLayer(layer: Layer3D): void;
2114
+ /** Re-fit the axes to the data and redraw — call after a layer's `setData(...)`. */
2115
+ refresh(): void;
1271
2116
  destroy(): void;
1272
2117
  private recompute;
1273
2118
  /** Build tick-mark line geometry + tick/title labels from the data bounds. */
@@ -1275,12 +2120,41 @@ declare class Plot3D {
1275
2120
  private resize;
1276
2121
  requestRender(): void;
1277
2122
  private viewProj;
2123
+ /** Build + draw grid lines on the 3 back walls (cube space) for the current eye. */
2124
+ private drawGridPlanes;
1278
2125
  render(): void;
2126
+ /** DOM legend of named, solid-colored layers. */
2127
+ private updateLegend;
2128
+ /** DOM colorbar for the first colormapped layer (gradient + value range). */
2129
+ private updateColorbar;
1279
2130
  private drawLabels;
1280
2131
  private attachControls;
1281
2132
  private buildControls;
1282
2133
  }
1283
2134
 
2135
+ /**
2136
+ * Marching cubes: extract a triangle-mesh isosurface from a 3D scalar volume.
2137
+ * Pure and unit-tested. Uses the canonical Bourke/Bloyd edge + triangle tables.
2138
+ *
2139
+ * The volume is indexed `x + y*nx + z*nx*ny`. A corner is "inside" when its value
2140
+ * is below `isoLevel`. Vertex positions are linearly interpolated along the crossed
2141
+ * cube edges; normals come from the (central-difference) volume gradient so the
2142
+ * surface shades smoothly.
2143
+ */
2144
+
2145
+ /**
2146
+ * Extract the isosurface of `values` (dims `nx*ny*nz`, index `x + y*nx + z*nx*ny`)
2147
+ * at `isoLevel`. Returns a triangle soup of world-space positions + smooth normals.
2148
+ */
2149
+ declare function marchingCubes(values: ArrayLike<number>, dims: [number, number, number], isoLevel: number, extent?: {
2150
+ x: Range;
2151
+ y: Range;
2152
+ z: Range;
2153
+ }): {
2154
+ positions: Float32Array;
2155
+ normals: Float32Array;
2156
+ };
2157
+
1284
2158
  /**
1285
2159
  * Owns the tick configuration for one axis and resolves the final tick list
1286
2160
  * against a scale. Modes: auto (delegates to the scale), custom (array), or
@@ -1372,9 +2246,31 @@ declare function createProgram(gl: WebGL2RenderingContext, vert: string, frag: s
1372
2246
  /** Cache uniform locations for a program by name. */
1373
2247
  declare function uniformLocations(gl: WebGL2RenderingContext, program: WebGLProgram, names: string[]): Record<string, WebGLUniformLocation | null>;
1374
2248
 
2249
+ /**
2250
+ * Ear-clipping polygon triangulation with hole support.
2251
+ *
2252
+ * A faithful reimplementation of the well-known ear-clipping algorithm (as
2253
+ * popularized by mapbox/earcut, ISC). Input is a flat `[x0,y0,x1,y1,…]`
2254
+ * coordinate array with optional hole start-indices; output is a flat list of
2255
+ * triangle vertex indices into that array. Pure and unit-tested.
2256
+ *
2257
+ * For rings above {@link Z_ORDER_THRESHOLD} vertices it switches on the z-order
2258
+ * (Morton) curve acceleration: each node gets a 32-bit Morton code, the nodes
2259
+ * are merge-sorted into a secondary z-linked list, and the "is this an ear?"
2260
+ * test only scans candidate points whose Morton code falls in the ear's
2261
+ * bounding-box range — turning the inner loop from O(n) into ~O(1) amortized,
2262
+ * so the whole triangulation goes from O(n²) to ~O(n log n). Small rings (most
2263
+ * vector-tile polygons) skip the hashing entirely to avoid its setup cost.
2264
+ */
2265
+ /**
2266
+ * Triangulate a polygon. `holeIndices[k]` is the vertex index (not coordinate
2267
+ * index) where hole `k` begins. Returns triangle vertex indices in groups of 3.
2268
+ */
2269
+ declare function earcut(data: number[], holeIndices?: number[], dim?: number): number[];
2270
+
1375
2271
  /** Parse a CSS hex/rgb color string into normalized RGBA (0..1). */
1376
2272
  declare function parseColor(input: string): [number, number, number, number];
1377
2273
  /** Normalized RGBA (0..1) back to a CSS `rgba(...)` string. */
1378
2274
  declare function toColorCss(c: readonly [number, number, number, number]): string;
1379
2275
 
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 };
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 };