@danielsimonjr/mathts-plot 0.4.1 → 0.4.3

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.
Files changed (45) hide show
  1. package/README.md +142 -142
  2. package/dist/coerce.d.ts +8 -0
  3. package/dist/coerce.d.ts.map +1 -0
  4. package/dist/contour.d.ts +6 -0
  5. package/dist/contour.d.ts.map +1 -0
  6. package/dist/emit.d.ts +5 -0
  7. package/dist/emit.d.ts.map +1 -0
  8. package/dist/frame.d.ts +4 -0
  9. package/dist/frame.d.ts.map +1 -0
  10. package/dist/heatmap.d.ts +4 -0
  11. package/dist/heatmap.d.ts.map +1 -0
  12. package/dist/histogram.d.ts +6 -0
  13. package/dist/histogram.d.ts.map +1 -0
  14. package/dist/index.d.ts +12 -106
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +14 -3
  17. package/dist/marks2d.d.ts +16 -0
  18. package/dist/marks2d.d.ts.map +1 -0
  19. package/dist/overlay.d.ts +4 -0
  20. package/dist/overlay.d.ts.map +1 -0
  21. package/dist/palette.d.ts +3 -0
  22. package/dist/palette.d.ts.map +1 -0
  23. package/dist/plot.d.ts +12 -0
  24. package/dist/plot.d.ts.map +1 -0
  25. package/dist/render-core.d.ts +21 -0
  26. package/dist/render-core.d.ts.map +1 -0
  27. package/dist/render-file.d.ts +9 -9
  28. package/dist/render-file.d.ts.map +1 -0
  29. package/dist/scale.d.ts +9 -0
  30. package/dist/scale.d.ts.map +1 -0
  31. package/dist/scene.d.ts +52 -0
  32. package/dist/scene.d.ts.map +1 -0
  33. package/dist/svg.d.ts +22 -0
  34. package/dist/svg.d.ts.map +1 -0
  35. package/dist/three/points3d.d.ts +11 -0
  36. package/dist/three/points3d.d.ts.map +1 -0
  37. package/dist/three/project.d.ts +11 -0
  38. package/dist/three/project.d.ts.map +1 -0
  39. package/dist/three/surface.d.ts +28 -0
  40. package/dist/three/surface.d.ts.map +1 -0
  41. package/dist/tikz.d.ts +8 -0
  42. package/dist/tikz.d.ts.map +1 -0
  43. package/dist/types.d.ts +42 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/package.json +13 -13
package/README.md CHANGED
@@ -1,142 +1,142 @@
1
- # @danielsimonjr/mathts-plot
2
-
3
- Headless SVG 2D/3D plotting for [MathTS](https://github.com/danielsimonjr/mathts).
4
-
5
- Pure functions returning self-contained SVG strings — no browser, no canvas, no runtime
6
- dependencies beyond the MathTS bedrock (`core`/`functions`/`expression`). Every function
7
- coerces its input and never throws on bad data: empty, `NaN`, or `Infinity` inputs render a
8
- "no data" placeholder SVG instead of crashing. See
9
- `docs/superpowers/specs/2026-07-07-plotting-design.md` for the design.
10
-
11
- ## Install
12
-
13
- ```sh
14
- npm install @danielsimonjr/mathts-plot
15
- ```
16
-
17
- ## Usage
18
-
19
- Every function below returns a self-contained SVG string (`<svg ...>...</svg>`) — render it
20
- directly in an `<img src="data:image/svg+xml,...">`, write it to a `.svg` file, or drop it
21
- into HTML.
22
-
23
- ### `line` — one series, or overlaid with others
24
-
25
- ```ts
26
- import { line } from '@danielsimonjr/mathts-plot';
27
-
28
- const svg = line([0, 1, 2, 3], [0, 1, 4, 9], { title: 'squares', xLabel: 'x', yLabel: 'y' });
29
- // svg === '<svg ...>...</svg>'
30
- ```
31
-
32
- ### `overlay` — combine several layers on shared, auto-scaled axes
33
-
34
- ```ts
35
- import { overlay } from '@danielsimonjr/mathts-plot';
36
-
37
- const svg = overlay(
38
- [
39
- { type: 'line', x: [0, 1, 2], y: [0, 1, 2], label: 'model' },
40
- { type: 'scatter', x: [0, 1, 2], y: [0.1, 1.2, 1.8], label: 'data' },
41
- ],
42
- { legend: true }
43
- );
44
- ```
45
-
46
- ### `surface` — 3D surface via orthographic projection + painter's algorithm
47
-
48
- ```ts
49
- import { surface } from '@danielsimonjr/mathts-plot';
50
-
51
- const z = [
52
- [0, 1, 2],
53
- [1, 2, 3],
54
- [2, 3, 4],
55
- ]; // z[row][col]
56
- const svg = surface(z, { kind: 'filled', azim: 45, elev: 25 });
57
- ```
58
-
59
- ### `plot` — generic, polymorphic entry point (including expression strings)
60
-
61
- ```ts
62
- import { plot } from '@danielsimonjr/mathts-plot';
63
-
64
- // numeric series → line
65
- plot([0, 1, 4, 9]);
66
- plot([0, 1, 2, 3], [0, 1, 4, 9]);
67
-
68
- // expression string, sampled via functions/expression → line
69
- plot('sin(x)', { from: 0, to: Math.PI, samples: 200 });
70
-
71
- // two free variables → contour (default) or 3D surface
72
- plot('x^2 + y^2', { from: -2, to: 2 });
73
- plot('x^2 + y^2', { from: -2, to: 2, kind: 'surface' });
74
-
75
- // array of Layer2D → overlay
76
- plot([
77
- { type: 'line', x: [0, 1, 2], y: [0, 1, 2] },
78
- { type: 'scatter', x: [0, 1, 2], y: [0.1, 1.2, 1.8] },
79
- ]);
80
- ```
81
-
82
- ### TikZ / LaTeX output
83
-
84
- Every function also accepts `{ format: 'tikz' }` (default is `'svg'`), and there's a
85
- generic `toTikZ()` mirroring `plot()`. The geometry matches the SVG output exactly (a
86
- deterministic y-flip maps SVG's top-left origin to TikZ's bottom-left); only
87
- `\usepackage{tikz}` is required to compile the result.
88
-
89
- ```ts
90
- import { toTikZ, line, surface } from '@danielsimonjr/mathts-plot';
91
-
92
- // generic entry point, expression source → line
93
- const tex = toTikZ('sin(x)', { from: 0, to: Math.PI });
94
-
95
- // per-type function via the format option
96
- const tex2 = line([0, 1, 2, 3], [0, 1, 4, 9], { format: 'tikz' });
97
-
98
- // standalone: false → a bare tikzpicture for \input, not a compilable document
99
- const z = [
100
- [0, 1, 2],
101
- [1, 2, 3],
102
- [2, 3, 4],
103
- ];
104
- const fragment = surface(z, { format: 'tikz', tikz: { standalone: false } });
105
- ```
106
-
107
- `toTikZ`/`{ format: 'tikz' }` return a LaTeX string, not SVG. With `standalone`
108
- (default `true`) the string is a complete `\documentclass{...}` document you can
109
- compile as-is; `standalone: false` returns just the `tikzpicture` environment, meant
110
- to be pulled in via `\input{...}` from a larger document.
111
-
112
- ## What it provides
113
-
114
- Per-type mark functions, each `(x, y, opts?) => string` unless noted:
115
-
116
- - **2D**: `line`, `scatter`, `bar`, `area`, `step`, `errorbar(x, y, yerr, opts?)`,
117
- `quiver(x, y, u, v, opts?)`.
118
- - **`histogram(data, opts?)`** — bins via `functions.histogram`, then renders bar heights at
119
- bin centers.
120
- - **`heatmap(z, opts?)`** — viridis-colored grid, `z` as `z[row][col]`.
121
- - **`contour(z, opts?)`** — marching squares over a `z[row][col]` grid.
122
- - **`overlay(layers, opts?)`** — several `Layer2D`s on shared, auto-scaled axes.
123
- - **3D**: `surface(z, opts?)` (wireframe or painter's-algorithm filled),
124
- `scatter3d(x, y, z, opts?)`, `curve3d(x, y, z, opts?)` — all projected with an orthographic
125
- camera (`azim`/`elev`).
126
- - **`plot(...)`** — generic polymorphic dispatch over numeric series, layer arrays, and
127
- expression-source strings (evaluated via `@danielsimonjr/mathts-expression` /
128
- `@danielsimonjr/mathts-functions`).
129
- - **`viridis(t)`** — the perceptually-uniform colormap used by `heatmap`/`contour`/`surface`,
130
- exposed for reuse.
131
-
132
- Notes:
133
-
134
- - Pure ESM, `strict` TypeScript, no runtime dependencies beyond the MathTS bedrock
135
- (`core`/`functions`/`expression`).
136
- - SVG-only in v1 — no PNG/canvas rendering.
137
- - `workbook` renders its charts through this package (its former private `svg.ts` plotter was
138
- removed).
139
-
140
- ## License
141
-
142
- MIT (c) Daniel Simon Jr.
1
+ # @danielsimonjr/mathts-plot
2
+
3
+ Headless SVG 2D/3D plotting for [MathTS](https://github.com/danielsimonjr/mathts).
4
+
5
+ Pure functions returning self-contained SVG strings — no browser, no canvas, no runtime
6
+ dependencies beyond the MathTS bedrock (`core`/`functions`/`expression`). Every function
7
+ coerces its input and never throws on bad data: empty, `NaN`, or `Infinity` inputs render a
8
+ "no data" placeholder SVG instead of crashing. See
9
+ `docs/superpowers/specs/2026-07-07-plotting-design.md` for the design.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ npm install @danielsimonjr/mathts-plot
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ Every function below returns a self-contained SVG string (`<svg ...>...</svg>`) — render it
20
+ directly in an `<img src="data:image/svg+xml,...">`, write it to a `.svg` file, or drop it
21
+ into HTML.
22
+
23
+ ### `line` — one series, or overlaid with others
24
+
25
+ ```ts
26
+ import { line } from '@danielsimonjr/mathts-plot';
27
+
28
+ const svg = line([0, 1, 2, 3], [0, 1, 4, 9], { title: 'squares', xLabel: 'x', yLabel: 'y' });
29
+ // svg === '<svg ...>...</svg>'
30
+ ```
31
+
32
+ ### `overlay` — combine several layers on shared, auto-scaled axes
33
+
34
+ ```ts
35
+ import { overlay } from '@danielsimonjr/mathts-plot';
36
+
37
+ const svg = overlay(
38
+ [
39
+ { type: 'line', x: [0, 1, 2], y: [0, 1, 2], label: 'model' },
40
+ { type: 'scatter', x: [0, 1, 2], y: [0.1, 1.2, 1.8], label: 'data' },
41
+ ],
42
+ { legend: true }
43
+ );
44
+ ```
45
+
46
+ ### `surface` — 3D surface via orthographic projection + painter's algorithm
47
+
48
+ ```ts
49
+ import { surface } from '@danielsimonjr/mathts-plot';
50
+
51
+ const z = [
52
+ [0, 1, 2],
53
+ [1, 2, 3],
54
+ [2, 3, 4],
55
+ ]; // z[row][col]
56
+ const svg = surface(z, { kind: 'filled', azim: 45, elev: 25 });
57
+ ```
58
+
59
+ ### `plot` — generic, polymorphic entry point (including expression strings)
60
+
61
+ ```ts
62
+ import { plot } from '@danielsimonjr/mathts-plot';
63
+
64
+ // numeric series → line
65
+ plot([0, 1, 4, 9]);
66
+ plot([0, 1, 2, 3], [0, 1, 4, 9]);
67
+
68
+ // expression string, sampled via functions/expression → line
69
+ plot('sin(x)', { from: 0, to: Math.PI, samples: 200 });
70
+
71
+ // two free variables → contour (default) or 3D surface
72
+ plot('x^2 + y^2', { from: -2, to: 2 });
73
+ plot('x^2 + y^2', { from: -2, to: 2, kind: 'surface' });
74
+
75
+ // array of Layer2D → overlay
76
+ plot([
77
+ { type: 'line', x: [0, 1, 2], y: [0, 1, 2] },
78
+ { type: 'scatter', x: [0, 1, 2], y: [0.1, 1.2, 1.8] },
79
+ ]);
80
+ ```
81
+
82
+ ### TikZ / LaTeX output
83
+
84
+ Every function also accepts `{ format: 'tikz' }` (default is `'svg'`), and there's a
85
+ generic `toTikZ()` mirroring `plot()`. The geometry matches the SVG output exactly (a
86
+ deterministic y-flip maps SVG's top-left origin to TikZ's bottom-left); only
87
+ `\usepackage{tikz}` is required to compile the result.
88
+
89
+ ```ts
90
+ import { toTikZ, line, surface } from '@danielsimonjr/mathts-plot';
91
+
92
+ // generic entry point, expression source → line
93
+ const tex = toTikZ('sin(x)', { from: 0, to: Math.PI });
94
+
95
+ // per-type function via the format option
96
+ const tex2 = line([0, 1, 2, 3], [0, 1, 4, 9], { format: 'tikz' });
97
+
98
+ // standalone: false → a bare tikzpicture for \input, not a compilable document
99
+ const z = [
100
+ [0, 1, 2],
101
+ [1, 2, 3],
102
+ [2, 3, 4],
103
+ ];
104
+ const fragment = surface(z, { format: 'tikz', tikz: { standalone: false } });
105
+ ```
106
+
107
+ `toTikZ`/`{ format: 'tikz' }` return a LaTeX string, not SVG. With `standalone`
108
+ (default `true`) the string is a complete `\documentclass{...}` document you can
109
+ compile as-is; `standalone: false` returns just the `tikzpicture` environment, meant
110
+ to be pulled in via `\input{...}` from a larger document.
111
+
112
+ ## What it provides
113
+
114
+ Per-type mark functions, each `(x, y, opts?) => string` unless noted:
115
+
116
+ - **2D**: `line`, `scatter`, `bar`, `area`, `step`, `errorbar(x, y, yerr, opts?)`,
117
+ `quiver(x, y, u, v, opts?)`.
118
+ - **`histogram(data, opts?)`** — bins via `functions.histogram`, then renders bar heights at
119
+ bin centers.
120
+ - **`heatmap(z, opts?)`** — viridis-colored grid, `z` as `z[row][col]`.
121
+ - **`contour(z, opts?)`** — marching squares over a `z[row][col]` grid.
122
+ - **`overlay(layers, opts?)`** — several `Layer2D`s on shared, auto-scaled axes.
123
+ - **3D**: `surface(z, opts?)` (wireframe or painter's-algorithm filled),
124
+ `scatter3d(x, y, z, opts?)`, `curve3d(x, y, z, opts?)` — all projected with an orthographic
125
+ camera (`azim`/`elev`).
126
+ - **`plot(...)`** — generic polymorphic dispatch over numeric series, layer arrays, and
127
+ expression-source strings (evaluated via `@danielsimonjr/mathts-expression` /
128
+ `@danielsimonjr/mathts-functions`).
129
+ - **`viridis(t)`** — the perceptually-uniform colormap used by `heatmap`/`contour`/`surface`,
130
+ exposed for reuse.
131
+
132
+ Notes:
133
+
134
+ - Pure ESM, `strict` TypeScript, no runtime dependencies beyond the MathTS bedrock
135
+ (`core`/`functions`/`expression`).
136
+ - SVG-only in v1 — no PNG/canvas rendering.
137
+ - `workbook` renders its charts through this package (its former private `svg.ts` plotter was
138
+ removed).
139
+
140
+ ## License
141
+
142
+ MIT (c) Daniel Simon Jr.
@@ -0,0 +1,8 @@
1
+ import type { Data } from './types.js';
2
+ /** Flatten + coerce to finite numbers; non-finite entries are dropped. */
3
+ export declare function coerce1d(raw: Data): number[];
4
+ /** Like coerce1d but position-preserving: non-finite stays NaN (no dropping). */
5
+ export declare function coerce1dPositional(raw: Data): number[];
6
+ /** Coerce a 2-D grid; each cell → number (non-finite kept as NaN gaps). */
7
+ export declare function coerce2d(raw: Data): number[][];
8
+ //# sourceMappingURL=coerce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../src/coerce.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AA6BvC,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM,EAAE,CAS5C;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM,EAAE,CAItD;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM,EAAE,EAAE,CAU9C"}
@@ -0,0 +1,6 @@
1
+ import type { PlotOptions } from './types.js';
2
+ /** Contour plot via marching squares over grid z[row][col]. */
3
+ export declare function contour(z: unknown, opts?: PlotOptions & {
4
+ levels?: number;
5
+ }): string;
6
+ //# sourceMappingURL=contour.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contour.d.ts","sourceRoot":"","sources":["../src/contour.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,+DAA+D;AAC/D,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAoFxF"}
package/dist/emit.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import type { Scene } from './scene.js';
2
+ import type { PlotOptions } from './types.js';
3
+ /** Serialize a Scene via the backend chosen by opts.format (default 'svg'). */
4
+ export declare function emit(scene: Scene, opts?: Pick<PlotOptions, 'format' | 'tikz'>): string;
5
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,+EAA+E;AAC/E,wBAAgB,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,CAAM,GAAG,MAAM,CAE1F"}
@@ -0,0 +1,4 @@
1
+ import type { Layer2D, PlotOptions } from './types.js';
2
+ /** Shared 2-D rendering core: builds a Scene (axes+ticks+grid+labels+legend+marks). Never throws. */
3
+ export declare function draw2D(layers: Layer2D[], opts?: PlotOptions): string;
4
+ //# sourceMappingURL=frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../src/frame.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiCvD,qGAAqG;AACrG,wBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,GAAE,WAAgB,GAAG,MAAM,CA2JxE"}
@@ -0,0 +1,4 @@
1
+ import type { PlotOptions } from './types.js';
2
+ /** Heatmap of a 2-D grid z[row][col], colored by viridis over the data range. */
3
+ export declare function heatmap(z: unknown, opts?: PlotOptions): string;
4
+ //# sourceMappingURL=heatmap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heatmap.d.ts","sourceRoot":"","sources":["../src/heatmap.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,iFAAiF;AACjF,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,WAAgB,GAAG,MAAM,CA+DlE"}
@@ -0,0 +1,6 @@
1
+ import type { PlotOptions } from './types.js';
2
+ /** Histogram: bins via functions.histogram, then renders bar heights at bin centers. */
3
+ export declare function histogram(data: unknown, opts?: PlotOptions & {
4
+ bins?: number;
5
+ }): string;
6
+ //# sourceMappingURL=histogram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"histogram.d.ts","sourceRoot":"","sources":["../src/histogram.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wFAAwF;AACxF,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,GAAE,WAAW,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAY3F"}
package/dist/index.d.ts CHANGED
@@ -1,106 +1,12 @@
1
- /** Anything the plotter accepts as a data series: numbers, typed arrays, or core values. */
2
- type Data = unknown;
3
- /** A 2-D coordinate axis. */
4
- interface AxisSpec {
5
- label?: string;
6
- scale?: 'linear' | 'log';
7
- }
8
- /** Options shared by all plot functions (each uses the subset it needs). */
9
- interface PlotOptions {
10
- title?: string;
11
- xLabel?: string;
12
- yLabel?: string;
13
- x?: AxisSpec;
14
- y?: AxisSpec;
15
- width?: number;
16
- height?: number;
17
- theme?: 'light' | 'dark';
18
- palette?: readonly string[];
19
- legend?: boolean;
20
- from?: number;
21
- to?: number;
22
- samples?: number;
23
- kind?: '2d' | '3d' | 'surface';
24
- scope?: Record<string, unknown>;
25
- format?: 'svg' | 'tikz';
26
- tikz?: {
27
- standalone?: boolean;
28
- scale?: number;
29
- };
30
- }
31
- /** One drawable 2-D layer for the shared draw2D core / overlay. */
32
- interface Layer2D {
33
- type: 'line' | 'scatter' | 'bar' | 'area' | 'step' | 'errorbar' | 'quiver';
34
- x?: Data;
35
- y: Data;
36
- yerr?: Data;
37
- u?: Data;
38
- v?: Data;
39
- label?: string;
40
- color?: string;
41
- }
42
-
43
- /**
44
- * Generic entry point. Data forms:
45
- * plot(y, opts?) → line, x = 0..n-1
46
- * plot(x, y, opts?) → line
47
- * plot(layers[], opts?) → overlay
48
- * plot(source, opts?) → expression sampling (line / contour / surface)
49
- */
50
- declare function plot(a: unknown, b?: unknown, c?: PlotOptions): string;
51
- /** Generic TikZ entry — same polymorphism as plot(), forced to the TikZ backend. */
52
- declare function toTikZ(a: unknown, b?: unknown, c?: PlotOptions): string;
53
-
54
- /** Public: line chart of one or many series. */
55
- declare function line(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
56
- /** Public: scatter plot of one or many series. */
57
- declare function scatter(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
58
- /** Public: bar chart of one or many series. */
59
- declare function bar(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
60
- /** Public: filled area under one or many series. */
61
- declare function area(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
62
- /** Public: step chart (horizontal-then-vertical) of one or many series. */
63
- declare function step(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
64
- /** Public: vertical error bars (whisker + point) for one or many series. */
65
- declare function errorbar(x: Layer2D['x'], y: Layer2D['y'], yerr: Layer2D['yerr'], opts?: PlotOptions): string;
66
- /** Public: 2-D vector field (arrows) of one or many series. */
67
- declare function quiver(x: Layer2D['x'], y: Layer2D['y'], u: Layer2D['u'], v: Layer2D['v'], opts?: PlotOptions): string;
68
-
69
- /** Histogram: bins via functions.histogram, then renders bar heights at bin centers. */
70
- declare function histogram(data: unknown, opts?: PlotOptions & {
71
- bins?: number;
72
- }): string;
73
-
74
- /** Heatmap of a 2-D grid z[row][col], colored by viridis over the data range. */
75
- declare function heatmap(z: unknown, opts?: PlotOptions): string;
76
-
77
- /** Contour plot via marching squares over grid z[row][col]. */
78
- declare function contour(z: unknown, opts?: PlotOptions & {
79
- levels?: number;
80
- }): string;
81
-
82
- /** Draw several 2-D layers (of any mix of types) on shared auto-scaled axes. */
83
- declare function overlay(layers: Layer2D[], opts?: PlotOptions): string;
84
-
85
- /** 3-D surface z[row][col], projected to 2-D SVG. Painter's algorithm for `filled`. */
86
- declare function surface(z: unknown, opts?: Omit<PlotOptions, 'kind'> & {
87
- azim?: number;
88
- elev?: number;
89
- kind?: 'wireframe' | 'filled';
90
- }): string;
91
-
92
- interface P3Opts extends PlotOptions {
93
- azim?: number;
94
- elev?: number;
95
- }
96
- /** 3-D scatter of (x,y,z) point triples, projected to 2-D SVG. */
97
- declare function scatter3d(x: unknown, y: unknown, z: unknown, opts?: P3Opts): string;
98
- /** Parametric 3-D curve through (x,y,z) coordinate arrays. */
99
- declare function curve3d(x: unknown, y: unknown, z: unknown, opts?: P3Opts): string;
100
-
101
- /** viridis colormap: t in [0,1] → "#rrggbb". */
102
- declare function viridis(t: number): string;
103
-
104
- declare const VERSION: string;
105
-
106
- export { type AxisSpec, type Data, type Layer2D, type PlotOptions, VERSION, area, bar, contour, curve3d, errorbar, heatmap, histogram, line, overlay, plot, quiver, scatter, scatter3d, step, surface, toTikZ, viridis };
1
+ export declare const VERSION: string;
2
+ export type { Data, PlotOptions, AxisSpec, Layer2D } from './types.js';
3
+ export { plot, toTikZ } from './plot.js';
4
+ export { line, scatter, bar, area, step, errorbar, quiver } from './marks2d.js';
5
+ export { histogram } from './histogram.js';
6
+ export { heatmap } from './heatmap.js';
7
+ export { contour } from './contour.js';
8
+ export { overlay } from './overlay.js';
9
+ export { surface } from './three/surface.js';
10
+ export { scatter3d, curve3d } from './three/points3d.js';
11
+ export { viridis } from './palette.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,EAAE,MAAwB,CAAC;AAE/C,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -748,6 +748,12 @@ function project(p, cam) {
748
748
 
749
749
  // src/three/surface.ts
750
750
  var MARGIN3 = 40;
751
+ var DEPTH_EPS = 1e-9;
752
+ function compareDepth(a, b) {
753
+ const d = b.depth - a.depth;
754
+ if (Math.abs(d) > DEPTH_EPS) return d;
755
+ return a.index - b.index;
756
+ }
751
757
  function surface(z, opts = {}) {
752
758
  const width = opts.width ?? 520;
753
759
  const height = opts.height ?? 320;
@@ -826,10 +832,15 @@ function surface(z, opts = {}) {
826
832
  const corners = [proj[r][c], proj[r][c + 1], proj[r + 1][c + 1], proj[r + 1][c]];
827
833
  const depth = (corners[0][2] + corners[1][2] + corners[2][2] + corners[3][2]) / 4;
828
834
  const meanZ = (grid[r][c] + grid[r][c + 1] + grid[r + 1][c + 1] + grid[r + 1][c]) / 4;
829
- quads.push({ depth, pts: corners.map(toScreen), shade: (meanZ - zlo) / zspan });
835
+ quads.push({
836
+ depth,
837
+ index: quads.length,
838
+ pts: corners.map(toScreen),
839
+ shade: (meanZ - zlo) / zspan
840
+ });
830
841
  }
831
842
  }
832
- quads.sort((a, b) => b.depth - a.depth);
843
+ quads.sort(compareDepth);
833
844
  for (const q of quads)
834
845
  prims.push({ k: "polygon", pts: q.pts, fill: viridis(q.shade), stroke: theme.grid });
835
846
  }
@@ -1117,7 +1128,7 @@ function curve3d(x, y, z, opts = {}) {
1117
1128
  }
1118
1129
 
1119
1130
  // src/index.ts
1120
- var VERSION = "0.4.1";
1131
+ var VERSION = "0.4.3";
1121
1132
  export {
1122
1133
  VERSION,
1123
1134
  area,
@@ -0,0 +1,16 @@
1
+ import type { Layer2D, PlotOptions } from './types.js';
2
+ /** Public: line chart of one or many series. */
3
+ export declare function line(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
4
+ /** Public: scatter plot of one or many series. */
5
+ export declare function scatter(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
6
+ /** Public: bar chart of one or many series. */
7
+ export declare function bar(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
8
+ /** Public: filled area under one or many series. */
9
+ export declare function area(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
10
+ /** Public: step chart (horizontal-then-vertical) of one or many series. */
11
+ export declare function step(x: Layer2D['x'], y: Layer2D['y'], opts?: PlotOptions): string;
12
+ /** Public: vertical error bars (whisker + point) for one or many series. */
13
+ export declare function errorbar(x: Layer2D['x'], y: Layer2D['y'], yerr: Layer2D['yerr'], opts?: PlotOptions): string;
14
+ /** Public: 2-D vector field (arrows) of one or many series. */
15
+ export declare function quiver(x: Layer2D['x'], y: Layer2D['y'], u: Layer2D['u'], v: Layer2D['v'], opts?: PlotOptions): string;
16
+ //# sourceMappingURL=marks2d.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marks2d.d.ts","sourceRoot":"","sources":["../src/marks2d.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,gDAAgD;AAChD,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAEjF;AAED,kDAAkD;AAClD,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAEpF;AAED,+CAA+C;AAC/C,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAEhF;AAED,oDAAoD;AACpD,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAEjF;AAED,2EAA2E;AAC3E,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAEjF;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CACtB,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACf,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACf,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EACrB,IAAI,CAAC,EAAE,WAAW,GACjB,MAAM,CAER;AAED,+DAA+D;AAC/D,wBAAgB,MAAM,CACpB,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACf,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACf,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACf,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACf,IAAI,CAAC,EAAE,WAAW,GACjB,MAAM,CAER"}
@@ -0,0 +1,4 @@
1
+ import type { Layer2D, PlotOptions } from './types.js';
2
+ /** Draw several 2-D layers (of any mix of types) on shared auto-scaled axes. */
3
+ export declare function overlay(layers: Layer2D[], opts?: PlotOptions): string;
4
+ //# sourceMappingURL=overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAErE"}
@@ -0,0 +1,3 @@
1
+ /** viridis colormap: t in [0,1] → "#rrggbb". */
2
+ export declare function viridis(t: number): string;
3
+ //# sourceMappingURL=palette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../src/palette.ts"],"names":[],"mappings":"AAeA,gDAAgD;AAChD,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAWzC"}
package/dist/plot.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { PlotOptions } from './types.js';
2
+ /**
3
+ * Generic entry point. Data forms:
4
+ * plot(y, opts?) → line, x = 0..n-1
5
+ * plot(x, y, opts?) → line
6
+ * plot(layers[], opts?) → overlay
7
+ * plot(source, opts?) → expression sampling (line / contour / surface)
8
+ */
9
+ export declare function plot(a: unknown, b?: unknown, c?: PlotOptions): string;
10
+ /** Generic TikZ entry — same polymorphism as plot(), forced to the TikZ backend. */
11
+ export declare function toTikZ(a: unknown, b?: unknown, c?: PlotOptions): string;
12
+ //# sourceMappingURL=plot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plot.d.ts","sourceRoot":"","sources":["../src/plot.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAW,WAAW,EAAE,MAAM,YAAY,CAAC;AAuEvD;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAMrE;AAED,oFAAoF;AACpF,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAavE"}
@@ -0,0 +1,21 @@
1
+ import type { Theme } from './svg.js';
2
+ import type { Layer2D } from './types.js';
3
+ import type { Prim } from './scene.js';
4
+ /**
5
+ * Shared rendering context, computed once per `draw2D` call and threaded
6
+ * through every layer's renderer. Lives here (not `frame.ts` or `marks2d.ts`)
7
+ * so both of those modules can depend on it without depending on each other.
8
+ */
9
+ export interface Frame {
10
+ px: (x: number) => number;
11
+ py: (y: number) => number;
12
+ xdom: [number, number];
13
+ ydom: [number, number];
14
+ theme: Theme;
15
+ width: number;
16
+ height: number;
17
+ color: (i: number) => string;
18
+ }
19
+ /** Dispatch a layer to its renderer (extended in later tasks). */
20
+ export declare function renderLayer(layer: Layer2D, f: Frame, i: number): Prim[];
21
+ //# sourceMappingURL=render-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-core.d.ts","sourceRoot":"","sources":["../src/render-core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;GAIG;AACH,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1B,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1B,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAC9B;AAuJD,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CAmBvE"}
@@ -1,10 +1,10 @@
1
1
  /** Thrown when an external tool is missing or a conversion fails. Deliberate
2
2
  * exception to plot's never-throw rule: I/O and missing tools must surface. */
3
- declare class PlotRenderError extends Error {
3
+ export declare class PlotRenderError extends Error {
4
4
  readonly missingTool?: string | undefined;
5
5
  constructor(message: string, missingTool?: string | undefined);
6
6
  }
7
- interface RenderOptions {
7
+ export interface RenderOptions {
8
8
  tool?: string;
9
9
  timeoutMs?: number;
10
10
  density?: number;
@@ -17,22 +17,22 @@ interface RunResult {
17
17
  }
18
18
  /** Spawn a command, feeding optional stdin, collecting stdout/stderr. Rejects
19
19
  * with PlotRenderError(ENOENT) if the binary is not found. */
20
- declare function runTool(cmd: string, args: string[], opts?: {
20
+ export declare function runTool(cmd: string, args: string[], opts?: {
21
21
  timeoutMs?: number;
22
22
  input?: string;
23
23
  }): Promise<RunResult>;
24
24
  /** True if `name` responds to a version probe (i.e. is on PATH). */
25
- declare function hasTool(name: string): Promise<boolean>;
25
+ export declare function hasTool(name: string): Promise<boolean>;
26
26
  /** SVG string → file. Extension of `outPath` selects the target: `.svg` writes
27
27
  * the SVG through; `.png`/`.pdf` convert via rsvg-convert (preferred) or resvg.
28
28
  * Rejects with PlotRenderError naming the tool to install if none is present. */
29
- declare function renderToFile(svg: string, outPath: string, opts?: RenderOptions): Promise<void>;
29
+ export declare function renderToFile(svg: string, outPath: string, opts?: RenderOptions): Promise<void>;
30
30
  /** Build the CLI args for a LaTeX engine. Shell-escape (\write18) is OFF
31
31
  * for security (arbitrary command execution during compile). */
32
- declare function latexArgs(engine: string, workDir: string, texPath: string): string[];
32
+ export declare function latexArgs(engine: string, workDir: string, texPath: string): string[];
33
33
  /** Standalone LaTeX/TikZ source → PDF via pdflatex (preferred) or tectonic.
34
34
  * Compiles in an OS temp dir and copies the resulting PDF to `outPath`.
35
35
  * Rejects with PlotRenderError naming the engine to install if none is found. */
36
- declare function latexToPdf(texSource: string, outPath: string, opts?: RenderOptions): Promise<void>;
37
-
38
- export { PlotRenderError, type RenderOptions, hasTool, latexArgs, latexToPdf, renderToFile, runTool };
36
+ export declare function latexToPdf(texSource: string, outPath: string, opts?: RenderOptions): Promise<void>;
37
+ export {};
38
+ //# sourceMappingURL=render-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-file.d.ts","sourceRoot":"","sources":["../src/render-file.ts"],"names":[],"mappings":"AAWA;gFACgF;AAChF,qBAAa,eAAgB,SAAQ,KAAK;IAGtC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM;IAF/B,YACE,OAAO,EAAE,MAAM,EACN,WAAW,CAAC,EAAE,MAAM,YAAA,EAI9B;CACF;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;+DAC+D;AAC/D,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,OAAO,CAAC,SAAS,CAAC,CAuBpB;AAED,oEAAoE;AACpE,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO5D;AAED;;kFAEkF;AAClF,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CA2Df;AAED;iEACiE;AACjE,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,MAAM,EAAE,CAcV;AAED;;kFAEkF;AAClF,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAwCf"}
@@ -0,0 +1,9 @@
1
+ /** [min, max] of a numeric array; a degenerate (flat) range is padded by ±1. */
2
+ export declare function extent(xs: readonly number[]): [number, number];
3
+ /** Linear map from data domain to pixel range. */
4
+ export declare function linearScale(dom: [number, number], range: [number, number]): (v: number) => number;
5
+ /** Log10 map; the domain is clamped to strictly-positive. */
6
+ export declare function logScale(dom: [number, number], range: [number, number]): (v: number) => number;
7
+ /** "Nice" round tick values covering [min,max] (Wilkinson-lite: 1/2/5 × 10^k step). */
8
+ export declare function niceTicks(min: number, max: number, count?: number): number[];
9
+ //# sourceMappingURL=scale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scale.d.ts","sourceRoot":"","sources":["../src/scale.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wBAAgB,MAAM,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAU9D;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAKjG;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAM9F;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE,CAWvE"}
@@ -0,0 +1,52 @@
1
+ /** Backend-agnostic drawing primitives. Marks build these; a backend serializes them. */
2
+ export type Prim = {
3
+ k: 'line';
4
+ x1: number;
5
+ y1: number;
6
+ x2: number;
7
+ y2: number;
8
+ stroke: string;
9
+ w: number;
10
+ opacity?: number;
11
+ } | {
12
+ k: 'circle';
13
+ cx: number;
14
+ cy: number;
15
+ r: number;
16
+ fill: string;
17
+ opacity?: number;
18
+ } | {
19
+ k: 'rect';
20
+ x: number;
21
+ y: number;
22
+ w: number;
23
+ h: number;
24
+ fill: string;
25
+ } | {
26
+ k: 'polyline';
27
+ pts: Array<[number, number]>;
28
+ stroke: string;
29
+ w: number;
30
+ } | {
31
+ k: 'polygon';
32
+ pts: Array<[number, number]>;
33
+ fill: string;
34
+ stroke: string;
35
+ } | {
36
+ k: 'text';
37
+ x: number;
38
+ y: number;
39
+ s: string;
40
+ fill: string;
41
+ anchor: 'start' | 'middle' | 'end';
42
+ size: number;
43
+ rotate?: number;
44
+ };
45
+ /** A complete drawable: canvas size, background, and an ordered list of primitives. */
46
+ export interface Scene {
47
+ width: number;
48
+ height: number;
49
+ bg: string;
50
+ prims: Prim[];
51
+ }
52
+ //# sourceMappingURL=scene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,MAAM,MAAM,IAAI,GACZ;IACE,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IAAE,CAAC,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,CAAC,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,CAAC,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5E;IACE,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,uFAAuF;AACvF,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,IAAI,EAAE,CAAC;CACf"}
package/dist/svg.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import type { Scene } from './scene.js';
2
+ export interface Theme {
3
+ fg: string;
4
+ muted: string;
5
+ grid: string;
6
+ axis: string;
7
+ bg: string;
8
+ series: string[];
9
+ }
10
+ export declare const THEMES: Record<'light' | 'dark', Theme>;
11
+ export declare function esc(s: string): string;
12
+ export declare function fmt(n: number): string;
13
+ export declare function svgDoc(width: number, height: number, body: string, bg: string): string;
14
+ export declare function line(x1: number, y1: number, x2: number, y2: number, stroke: string, w?: number, opacity?: number): string;
15
+ export declare function circle(cx: number, cy: number, r: number, fill: string, opacity?: number): string;
16
+ export declare function rect(x: number, y: number, w: number, h: number, fill: string): string;
17
+ export declare function polyline(pts: Array<[number, number]>, stroke: string, w?: number): string;
18
+ export declare function polygon(pts: Array<[number, number]>, fill: string, stroke?: string): string;
19
+ export declare function text(x: number, y: number, s: string, fill: string, anchor?: string, size?: number): string;
20
+ /** Serialize a Scene to a self-contained SVG string (reuses the exported builders). */
21
+ export declare function emitSVG(scene: Scene): string;
22
+ //# sourceMappingURL=svg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../src/svg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAQ,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAaD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,EAAE,KAAK,CAiBlD,CAAC;AAEF,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAErC;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKrC;AAID,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAKtF;AAED,wBAAgB,IAAI,CAClB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,CAAC,SAAI,EACL,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAMR;AACD,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAMhG;AACD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErF;AACD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,SAAI,GAAG,MAAM,CAGpF;AACD,wBAAgB,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAS,GAAG,MAAM,CAG3F;AACD,wBAAgB,IAAI,CAClB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,MAAM,EACZ,MAAM,SAAU,EAChB,IAAI,SAAK,GACR,MAAM,CAER;AAuBD,uFAAuF;AACvF,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAE5C"}
@@ -0,0 +1,11 @@
1
+ import type { PlotOptions } from '../types.js';
2
+ interface P3Opts extends PlotOptions {
3
+ azim?: number;
4
+ elev?: number;
5
+ }
6
+ /** 3-D scatter of (x,y,z) point triples, projected to 2-D SVG. */
7
+ export declare function scatter3d(x: unknown, y: unknown, z: unknown, opts?: P3Opts): string;
8
+ /** Parametric 3-D curve through (x,y,z) coordinate arrays. */
9
+ export declare function curve3d(x: unknown, y: unknown, z: unknown, opts?: P3Opts): string;
10
+ export {};
11
+ //# sourceMappingURL=points3d.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"points3d.d.ts","sourceRoot":"","sources":["../../src/three/points3d.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,UAAU,MAAO,SAAQ,WAAW;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA8HD,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,MAAW,GAAG,MAAM,CAEvF;AACD,8DAA8D;AAC9D,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,MAAW,GAAG,MAAM,CAErF"}
@@ -0,0 +1,11 @@
1
+ export interface Camera {
2
+ azim: number;
3
+ elev: number;
4
+ }
5
+ /**
6
+ * Orthographic projection of a 3-D point to screen [x, y, depth].
7
+ * Convention (azim=0, elev=0): world +x → screen +x, world +z → screen +y,
8
+ * world +y → into the screen (depth). Depth increases away from the viewer.
9
+ */
10
+ export declare function project(p: [number, number, number], cam: Camera): [number, number, number];
11
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/three/project.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAY1F"}
@@ -0,0 +1,28 @@
1
+ import type { PlotOptions } from '../types.js';
2
+ /**
3
+ * Depth tolerance for the painter's sort. Every vertex is normalised into the cube
4
+ * [-1, 1]^3 before projection, so |depth| <= sqrt(3) whatever the input data scale.
5
+ * Float rounding in the projection and the 4-corner mean moves a depth by a few ulp
6
+ * (~1e-16 at this scale); a real geometric difference between two quads of any grid
7
+ * up to 10^6 cells per side is >= ~1e-6. 1e-9 sits many orders of magnitude from both.
8
+ */
9
+ export declare const DEPTH_EPS = 1e-9;
10
+ /**
11
+ * Painter's-order comparator: far (large depth) first. Depths within {@link DEPTH_EPS}
12
+ * are a tie, and a tie falls back to the face index (lower index first), so the order
13
+ * never depends on the last bit of a float (which differs between runtimes' Math.sin).
14
+ */
15
+ export declare function compareDepth(a: {
16
+ depth: number;
17
+ index: number;
18
+ }, b: {
19
+ depth: number;
20
+ index: number;
21
+ }): number;
22
+ /** 3-D surface z[row][col], projected to 2-D SVG. Painter's algorithm for `filled`. */
23
+ export declare function surface(z: unknown, opts?: Omit<PlotOptions, 'kind'> & {
24
+ azim?: number;
25
+ elev?: number;
26
+ kind?: 'wireframe' | 'filled';
27
+ }): string;
28
+ //# sourceMappingURL=surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/three/surface.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,OAAO,CAAC;AAE9B;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACnC,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClC,MAAM,CAIR;AAED,uFAAuF;AACvF,wBAAgB,OAAO,CACrB,CAAC,EAAE,OAAO,EACV,IAAI,GAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;CAC1B,GACL,MAAM,CAiHR"}
package/dist/tikz.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { Scene } from './scene.js';
2
+ import type { PlotOptions } from './types.js';
3
+ /** Escape the LaTeX specials that break a plain \node body. Single-pass so an
4
+ * escape's own backslash/braces are never re-processed. */
5
+ export declare function texEsc(s: string): string;
6
+ /** Serialize a Scene to TikZ. Coordinates match the SVG (y-flipped for TikZ's y-up), scaled. */
7
+ export declare function emitTikZ(scene: Scene, opts?: PlotOptions): string;
8
+ //# sourceMappingURL=tikz.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tikz.d.ts","sourceRoot":"","sources":["../src/tikz.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAQ,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;2DAC2D;AAC3D,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAaxC;AA+DD,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,WAAgB,GAAG,MAAM,CAYrE"}
@@ -0,0 +1,42 @@
1
+ /** Anything the plotter accepts as a data series: numbers, typed arrays, or core values. */
2
+ export type Data = unknown;
3
+ /** A 2-D coordinate axis. */
4
+ export interface AxisSpec {
5
+ label?: string;
6
+ scale?: 'linear' | 'log';
7
+ }
8
+ /** Options shared by all plot functions (each uses the subset it needs). */
9
+ export interface PlotOptions {
10
+ title?: string;
11
+ xLabel?: string;
12
+ yLabel?: string;
13
+ x?: AxisSpec;
14
+ y?: AxisSpec;
15
+ width?: number;
16
+ height?: number;
17
+ theme?: 'light' | 'dark';
18
+ palette?: readonly string[];
19
+ legend?: boolean;
20
+ from?: number;
21
+ to?: number;
22
+ samples?: number;
23
+ kind?: '2d' | '3d' | 'surface';
24
+ scope?: Record<string, unknown>;
25
+ format?: 'svg' | 'tikz';
26
+ tikz?: {
27
+ standalone?: boolean;
28
+ scale?: number;
29
+ };
30
+ }
31
+ /** One drawable 2-D layer for the shared draw2D core / overlay. */
32
+ export interface Layer2D {
33
+ type: 'line' | 'scatter' | 'bar' | 'area' | 'step' | 'errorbar' | 'quiver';
34
+ x?: Data;
35
+ y: Data;
36
+ yerr?: Data;
37
+ u?: Data;
38
+ v?: Data;
39
+ label?: string;
40
+ color?: string;
41
+ }
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC;AAE3B,6BAA6B;AAC7B,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CAC1B;AAED,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,CAAC,EAAE,QAAQ,CAAC;IACb,CAAC,CAAC,EAAE,QAAQ,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED,mEAAmE;AACnE,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC3E,CAAC,CAAC,EAAE,IAAI,CAAC;IACT,CAAC,EAAE,IAAI,CAAC;IACR,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,CAAC,CAAC,EAAE,IAAI,CAAC;IACT,CAAC,CAAC,EAAE,IAAI,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@danielsimonjr/mathts-plot",
3
- "version": "0.4.1",
4
- "description": "Headless SVG 2D/3D plotting for MathTS — dependency-light, expression-aware, built on core/functions/expression",
3
+ "version": "0.4.3",
4
+ "description": "Headless SVG 2D/3D plotting for MathTS \u2014 dependency-light, expression-aware, built on core/functions/expression",
5
5
  "author": "Daniel Simon Jr.",
6
6
  "license": "MIT",
7
7
  "type": "module",
@@ -23,26 +23,26 @@
23
23
  "README.md"
24
24
  ],
25
25
  "scripts": {
26
- "build": "tsup",
26
+ "build": "tsup && tsc -p tsconfig.dts.json",
27
27
  "dev": "tsup --watch",
28
- "test": "vitest run",
28
+ "test": "bun test --isolate --timeout 30000",
29
29
  "test:watch": "vitest",
30
- "test:coverage": "vitest run --coverage",
30
+ "test:coverage": "bun test --isolate --timeout 30000 --coverage",
31
31
  "typecheck": "tsc --noEmit",
32
- "lint": "eslint src --ext .ts",
33
- "lint:fix": "eslint src --ext .ts --fix",
32
+ "lint": "oxlint src",
33
+ "lint:fix": "oxlint src --fix",
34
34
  "clean": "rm -rf dist"
35
35
  },
36
36
  "dependencies": {
37
- "@danielsimonjr/mathts-core": "^0.14.1",
38
- "@danielsimonjr/mathts-functions": "^0.63.0",
39
- "@danielsimonjr/mathts-expression": "^0.7.1"
37
+ "@danielsimonjr/mathts-core": "^0.15.0",
38
+ "@danielsimonjr/mathts-functions": "^0.64.1",
39
+ "@danielsimonjr/mathts-expression": "^0.8.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@types/node": "^25.5.2",
42
+ "@types/node": "^26.4.0",
43
43
  "tsup": "^8.0.0",
44
- "typescript": "^5.3.0",
45
- "vitest": "^4.1.10"
44
+ "typescript": "^7.0.2",
45
+ "vitest": "^5.0.0"
46
46
  },
47
47
  "publishConfig": {
48
48
  "access": "public"