@jarenjs/charts 0.34.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/README.md +293 -0
- package/dist/types/component/index.d.ts +95 -0
- package/dist/types/core/axis.d.ts +77 -0
- package/dist/types/core/cartesian.d.ts +127 -0
- package/dist/types/core/chart.d.ts +58 -0
- package/dist/types/core/domain.d.ts +96 -0
- package/dist/types/core/marks.d.ts +86 -0
- package/dist/types/core/palette.d.ts +72 -0
- package/dist/types/core/scale.d.ts +59 -0
- package/dist/types/core/session.d.ts +85 -0
- package/dist/types/core/stream-adapter.d.ts +187 -0
- package/dist/types/index.d.ts +35 -0
- package/dist/types/transforms/benchmark-adapter.d.ts +169 -0
- package/dist/types/transforms/mermaid-adapter.d.ts +30 -0
- package/dist/types/types/bar.d.ts +213 -0
- package/dist/types/types/boxplot.d.ts +116 -0
- package/dist/types/types/candlestick.d.ts +218 -0
- package/dist/types/types/gauge.d.ts +68 -0
- package/dist/types/types/heatmap.d.ts +104 -0
- package/dist/types/types/line.d.ts +272 -0
- package/dist/types/types/map.d.ts +137 -0
- package/dist/types/types/pie.d.ts +146 -0
- package/dist/types/types/radar.d.ts +89 -0
- package/dist/types/types/sankey.d.ts +100 -0
- package/dist/types/types/scatter.d.ts +80 -0
- package/dist/types/types/streamgraph.d.ts +75 -0
- package/dist/types/types/treemap.d.ts +118 -0
- package/package.json +76 -0
- package/schemas/chart-definition.schema.json +448 -0
- package/src/component/index.js +125 -0
- package/src/core/axis.js +221 -0
- package/src/core/cartesian.js +192 -0
- package/src/core/chart.js +101 -0
- package/src/core/domain.js +123 -0
- package/src/core/marks.js +110 -0
- package/src/core/palette.js +126 -0
- package/src/core/scale.js +106 -0
- package/src/core/session.js +0 -0
- package/src/core/stream-adapter.js +613 -0
- package/src/index.js +40 -0
- package/src/transforms/benchmark-adapter.js +298 -0
- package/src/transforms/mermaid-adapter.js +19 -0
- package/src/types/bar.js +276 -0
- package/src/types/boxplot.js +216 -0
- package/src/types/candlestick.js +274 -0
- package/src/types/gauge.js +140 -0
- package/src/types/heatmap.js +176 -0
- package/src/types/line.js +349 -0
- package/src/types/map.js +378 -0
- package/src/types/pie.js +163 -0
- package/src/types/radar.js +224 -0
- package/src/types/sankey.js +391 -0
- package/src/types/scatter.js +148 -0
- package/src/types/streamgraph.js +158 -0
- package/src/types/treemap.js +322 -0
- package/styles/charts.css +83 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Benchmark interop: pure functions from the published benchmark
|
|
3
|
+
* data shapes (the jaren website's generated `benchmarks/*.json`) to
|
|
4
|
+
* `compileChart`-shaped `{config, data}` pairs. No formatting, no
|
|
5
|
+
* vnodes, no fetching — data in, chart definition out, so every
|
|
6
|
+
* function is unit-testable against a vendored slice of the real data.
|
|
7
|
+
*
|
|
8
|
+
* The suite-wide ratio convention holds: ratio > 1 means "Jaren is N×
|
|
9
|
+
* faster", and the win/loss semantic tones follow it.
|
|
10
|
+
*/
|
|
11
|
+
export type ChartPair = {
|
|
12
|
+
config: Record<string, any>;
|
|
13
|
+
data: Record<string, any>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {{config: Record<string, any>, data: Record<string, any>}} ChartPair
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The ratio-distribution bar chart: success-only tests bucketed by
|
|
20
|
+
* ratio. Buckets carry their own predicate and tone.
|
|
21
|
+
* @param {{ratio: number|null, isSuccessTest?: boolean}[]} results
|
|
22
|
+
* @param {{label: string, test: (r: number) => boolean, tone: 'win'|'loss'}[]} buckets
|
|
23
|
+
* @param {string} [title]
|
|
24
|
+
* @returns {ChartPair}
|
|
25
|
+
*/
|
|
26
|
+
export declare function ratioDistributionBars(results: {
|
|
27
|
+
ratio: number | null;
|
|
28
|
+
isSuccessTest?: boolean;
|
|
29
|
+
}[], buckets: {
|
|
30
|
+
label: string;
|
|
31
|
+
test: (r: number) => boolean;
|
|
32
|
+
tone: 'win' | 'loss';
|
|
33
|
+
}[], title?: string): ChartPair;
|
|
34
|
+
/**
|
|
35
|
+
* The ratio scatter: every success-only test as one point, ranked
|
|
36
|
+
* fastest-ratio first, log-scale y, reference line at parity.
|
|
37
|
+
* @param {{ratio: number|null, isSuccessTest?: boolean}[]} results
|
|
38
|
+
* @param {string} [title]
|
|
39
|
+
* @returns {ChartPair}
|
|
40
|
+
*/
|
|
41
|
+
export declare function ratioScatter(results: {
|
|
42
|
+
ratio: number | null;
|
|
43
|
+
isSuccessTest?: boolean;
|
|
44
|
+
}[], title?: string): ChartPair;
|
|
45
|
+
/**
|
|
46
|
+
* Per-draft conformance: grouped bars of passed tests per engine.
|
|
47
|
+
* @param {Record<string, Record<string, {passed: number}>>} engineStats
|
|
48
|
+
* engine → draft → {passed, failed, errors}
|
|
49
|
+
* @param {string} [title]
|
|
50
|
+
* @returns {ChartPair}
|
|
51
|
+
*/
|
|
52
|
+
export declare function conformanceBars(engineStats: Record<string, Record<string, {
|
|
53
|
+
passed: number;
|
|
54
|
+
}>>, title?: string): ChartPair;
|
|
55
|
+
/**
|
|
56
|
+
* Generic engine-comparison bars over `{name, results: {engine: value}}`
|
|
57
|
+
* profile rows (the toml/markdown/mermaid profile shape).
|
|
58
|
+
* @param {{name: string, results: Record<string, number>}[]} rows
|
|
59
|
+
* @param {string[]} engines series order (first = jaren)
|
|
60
|
+
* @param {{title?: string, log?: boolean, valLabel?: string}} [options]
|
|
61
|
+
* @returns {ChartPair}
|
|
62
|
+
*/
|
|
63
|
+
export declare function profileBars(rows: {
|
|
64
|
+
name: string;
|
|
65
|
+
results: Record<string, number>;
|
|
66
|
+
}[], engines: string[], options?: {
|
|
67
|
+
title?: string;
|
|
68
|
+
log?: boolean;
|
|
69
|
+
valLabel?: string;
|
|
70
|
+
}): ChartPair;
|
|
71
|
+
/**
|
|
72
|
+
* Scenario-matrix bars over `{scenario|title, engines: {key: nsPerOp}}`
|
|
73
|
+
* rows (the jsonquery/jslt shape). Log axis — rival engines span orders
|
|
74
|
+
* of magnitude.
|
|
75
|
+
* @param {{scenario?: string, title?: string, engines: Record<string, number>}[]} rows
|
|
76
|
+
* @param {{title?: string, valLabel?: string}} [options]
|
|
77
|
+
* @returns {ChartPair}
|
|
78
|
+
*/
|
|
79
|
+
export declare function matrixBars(rows: {
|
|
80
|
+
scenario?: string;
|
|
81
|
+
title?: string;
|
|
82
|
+
engines: Record<string, number>;
|
|
83
|
+
}[], options?: {
|
|
84
|
+
title?: string;
|
|
85
|
+
valLabel?: string;
|
|
86
|
+
}): ChartPair;
|
|
87
|
+
/**
|
|
88
|
+
* Suite pass-count bars over an `{engine: {pass, total}}` map (the
|
|
89
|
+
* toml-compliance / markdown-scorecard shape); the highlighted engine
|
|
90
|
+
* (ours) carries the win tone.
|
|
91
|
+
* @param {Record<string, {pass: number, total: number}>} scorecard
|
|
92
|
+
* @param {{title?: string, highlight?: string, valLabel?: string}} [options]
|
|
93
|
+
* @returns {ChartPair}
|
|
94
|
+
*/
|
|
95
|
+
export declare function passCountBars(scorecard: Record<string, {
|
|
96
|
+
pass: number;
|
|
97
|
+
total: number;
|
|
98
|
+
}>, options?: {
|
|
99
|
+
title?: string;
|
|
100
|
+
highlight?: string;
|
|
101
|
+
valLabel?: string;
|
|
102
|
+
}): ChartPair;
|
|
103
|
+
/**
|
|
104
|
+
* The jsonpath per-query profile: horizontal grouped bars for the
|
|
105
|
+
* top-N queries by jaren-vs-rival spread (the rest stay in the table).
|
|
106
|
+
* @param {{name: string, engines: Record<string, number>}[]} rows
|
|
107
|
+
* @param {string} rival the comparison engine key (e.g. 'json-p3')
|
|
108
|
+
* @param {number} topN
|
|
109
|
+
* @param {string} [title]
|
|
110
|
+
* @returns {ChartPair}
|
|
111
|
+
*/
|
|
112
|
+
export declare function querySpreadBars(rows: {
|
|
113
|
+
name: string;
|
|
114
|
+
engines: Record<string, number>;
|
|
115
|
+
}[], rival: string, topN: number, title?: string): ChartPair;
|
|
116
|
+
/**
|
|
117
|
+
* Bars over a pointer/patch-style result table:
|
|
118
|
+
* `{columns, rows: [{name, results: number[]}]}`.
|
|
119
|
+
* @param {{title?: string, columns: string[], rows: {name: string, results: number[]}[]}} table
|
|
120
|
+
* @param {{title?: string, log?: boolean, valLabel?: string}} [options]
|
|
121
|
+
* @returns {ChartPair}
|
|
122
|
+
*/
|
|
123
|
+
export declare function resultTableBars(table: {
|
|
124
|
+
title?: string;
|
|
125
|
+
columns: string[];
|
|
126
|
+
rows: {
|
|
127
|
+
name: string;
|
|
128
|
+
results: number[];
|
|
129
|
+
}[];
|
|
130
|
+
}, options?: {
|
|
131
|
+
title?: string;
|
|
132
|
+
log?: boolean;
|
|
133
|
+
valLabel?: string;
|
|
134
|
+
}): ChartPair;
|
|
135
|
+
/**
|
|
136
|
+
* Horizontal bars over `{label, ns}` timing rows (the view/charts
|
|
137
|
+
* benchmark shape). One series in one color: the bars are *nominal*
|
|
138
|
+
* categories — engines or scenarios — so their identity comes from the
|
|
139
|
+
* axis label, not from a hue, and the length is the whole message.
|
|
140
|
+
* Semantic win/loss tones are deliberately not used: on a timing chart
|
|
141
|
+
* "ours" is not automatically good, and docs/DESIGN.md reserves those tokens
|
|
142
|
+
* for genuine status.
|
|
143
|
+
* @param {{label: string, ns: number}[]} rows
|
|
144
|
+
* @param {{title?: string, log?: boolean, valLabel?: string}} [options]
|
|
145
|
+
* @returns {ChartPair}
|
|
146
|
+
*/
|
|
147
|
+
export declare function timingBars(rows: {
|
|
148
|
+
label: string;
|
|
149
|
+
ns: number;
|
|
150
|
+
}[], options?: {
|
|
151
|
+
title?: string;
|
|
152
|
+
log?: boolean;
|
|
153
|
+
valLabel?: string;
|
|
154
|
+
}): ChartPair;
|
|
155
|
+
/**
|
|
156
|
+
* Cross-suite ratio bars for the benchmarks overview: one bar per suite
|
|
157
|
+
* headline, tone by which side of parity it lands on — here the tones
|
|
158
|
+
* ARE semantic (a ratio below 1 is a genuine loss, reported as one).
|
|
159
|
+
* @param {{key: string, label: string, ratio: number|null}[]} headlines
|
|
160
|
+
* @param {{title?: string}} [options]
|
|
161
|
+
* @returns {ChartPair}
|
|
162
|
+
*/
|
|
163
|
+
export declare function headlineRatioBars(headlines: {
|
|
164
|
+
key: string;
|
|
165
|
+
label: string;
|
|
166
|
+
ratio: number | null;
|
|
167
|
+
}[], options?: {
|
|
168
|
+
title?: string;
|
|
169
|
+
}): ChartPair;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Mermaid interop: map a mermaid pie AST (`{title, showData,
|
|
3
|
+
* slices}`) onto a chart definition + data pair. Lives in charts so the
|
|
4
|
+
* dependency arrow stays one-way — `@jarenjs/mermaid` imports this,
|
|
5
|
+
* never the reverse; nothing here touches mermaid code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Convert a mermaid pie AST to `compileChart`-shaped inputs.
|
|
9
|
+
* @param {{title?: string|null, showData?: boolean, slices: {label: string, value: number}[]}} ast
|
|
10
|
+
* @returns {{config: {type: 'pie', title: string|null}, data: {slices: {label: string, value: number}[]}}}
|
|
11
|
+
*/
|
|
12
|
+
export declare function mermaidPieToChartAST(ast: {
|
|
13
|
+
title?: string | null;
|
|
14
|
+
showData?: boolean;
|
|
15
|
+
slices: {
|
|
16
|
+
label: string;
|
|
17
|
+
value: number;
|
|
18
|
+
}[];
|
|
19
|
+
}): {
|
|
20
|
+
config: {
|
|
21
|
+
type: 'pie';
|
|
22
|
+
title: string | null;
|
|
23
|
+
};
|
|
24
|
+
data: {
|
|
25
|
+
slices: {
|
|
26
|
+
label: string;
|
|
27
|
+
value: number;
|
|
28
|
+
}[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The bar chart type: grouped or stacked, vertical or horizontal,
|
|
3
|
+
* linear or log value axis. Data shape:
|
|
4
|
+
*
|
|
5
|
+
* data = { categories: string[],
|
|
6
|
+
* series: [{ name, values: number[],
|
|
7
|
+
* tone?: 'win'|'loss', tones?: (('win'|'loss'|null)[]) }] }
|
|
8
|
+
* config = { type:'bar', title?, stacked?, log?, orient?: 'v'|'h',
|
|
9
|
+
* catLabel?, valLabel? }
|
|
10
|
+
*
|
|
11
|
+
* The AST is orientation-agnostic: `u` runs along the category axis,
|
|
12
|
+
* `v` along the value axis; the render maps them to x/y per `orient`.
|
|
13
|
+
* Category lookups are hoisted out of the series loop (index-driven,
|
|
14
|
+
* never `categories.indexOf` per cell — that is O(n²) for wide charts).
|
|
15
|
+
*/
|
|
16
|
+
export type BarAST = {
|
|
17
|
+
type: 'bar';
|
|
18
|
+
title: string | null;
|
|
19
|
+
orient: 'v' | 'h';
|
|
20
|
+
cat: {
|
|
21
|
+
ticks: {
|
|
22
|
+
pos: number;
|
|
23
|
+
label: string;
|
|
24
|
+
}[];
|
|
25
|
+
label: string | null;
|
|
26
|
+
};
|
|
27
|
+
val: {
|
|
28
|
+
ticks: {
|
|
29
|
+
pos: number;
|
|
30
|
+
label: string;
|
|
31
|
+
}[];
|
|
32
|
+
label: string | null;
|
|
33
|
+
};
|
|
34
|
+
legend: {
|
|
35
|
+
name: string;
|
|
36
|
+
swatch: number;
|
|
37
|
+
}[] | null;
|
|
38
|
+
bars: BarMarkAST[];
|
|
39
|
+
/**
|
|
40
|
+
* number of categories
|
|
41
|
+
*/
|
|
42
|
+
count: number;
|
|
43
|
+
/**
|
|
44
|
+
* resolved value-axis bounds
|
|
45
|
+
*/
|
|
46
|
+
domain: [number, number];
|
|
47
|
+
};
|
|
48
|
+
export type BarMarkAST = {
|
|
49
|
+
u0: number;
|
|
50
|
+
/**
|
|
51
|
+
* category-axis band
|
|
52
|
+
*/
|
|
53
|
+
u1: number;
|
|
54
|
+
v0: number;
|
|
55
|
+
/**
|
|
56
|
+
* value-axis extent
|
|
57
|
+
*/
|
|
58
|
+
v1: number;
|
|
59
|
+
/**
|
|
60
|
+
* series index
|
|
61
|
+
*/
|
|
62
|
+
series: number;
|
|
63
|
+
tone: 'win' | 'loss' | null;
|
|
64
|
+
/**
|
|
65
|
+
* the category this bar stands in
|
|
66
|
+
*/
|
|
67
|
+
label: string;
|
|
68
|
+
/**
|
|
69
|
+
* the series name
|
|
70
|
+
*/
|
|
71
|
+
name: string;
|
|
72
|
+
/**
|
|
73
|
+
* the drawn value (hover text reports it exactly)
|
|
74
|
+
*/
|
|
75
|
+
value: number;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* @typedef {object} BarAST
|
|
79
|
+
* @property {'bar'} type
|
|
80
|
+
* @property {string|null} title
|
|
81
|
+
* @property {'v'|'h'} orient
|
|
82
|
+
* @property {{ticks: {pos:number,label:string}[], label: string|null}} cat
|
|
83
|
+
* @property {{ticks: {pos:number,label:string}[], label: string|null}} val
|
|
84
|
+
* @property {{name: string, swatch: number}[]|null} legend
|
|
85
|
+
* @property {BarMarkAST[]} bars
|
|
86
|
+
* @property {number} count number of categories
|
|
87
|
+
* @property {[number, number]} domain resolved value-axis bounds
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* @typedef {object} BarMarkAST
|
|
91
|
+
* @property {number} u0 @property {number} u1 category-axis band
|
|
92
|
+
* @property {number} v0 @property {number} v1 value-axis extent
|
|
93
|
+
* @property {number} series series index
|
|
94
|
+
* @property {'win'|'loss'|null} tone
|
|
95
|
+
* @property {string} label the category this bar stands in
|
|
96
|
+
* @property {string} name the series name
|
|
97
|
+
* @property {number} value the drawn value (hover text reports it exactly)
|
|
98
|
+
*/
|
|
99
|
+
/**
|
|
100
|
+
* Scan the drawn values for the extremes the value axis is resolved
|
|
101
|
+
* from: the largest bar (a stacked chart's per-category total) and the
|
|
102
|
+
* smallest positive value a log axis needs for its bottom decade.
|
|
103
|
+
*
|
|
104
|
+
* Exported because the incremental session must reach the same bounds
|
|
105
|
+
* decision from the same numbers — one implementation, no drift.
|
|
106
|
+
* @param {any} data
|
|
107
|
+
* @param {boolean} stacked @param {boolean} log
|
|
108
|
+
* @returns {{maxVal: number, minPos: number}}
|
|
109
|
+
*/
|
|
110
|
+
export declare function scanBarExtremes(data: any, stacked: boolean, log: boolean): {
|
|
111
|
+
maxVal: number;
|
|
112
|
+
minPos: number;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Resolve the value-axis bounds and tick values from the scanned
|
|
116
|
+
* extremes: a nice-number top over a zero base, or whole decades under
|
|
117
|
+
* `log`. The AST records the bounds so a later build — or the session —
|
|
118
|
+
* can detect "unchanged".
|
|
119
|
+
* @param {{maxVal: number, minPos: number}} ext
|
|
120
|
+
* @param {boolean} log
|
|
121
|
+
* @returns {{domain: [number, number], tickValues: number[]}}
|
|
122
|
+
*/
|
|
123
|
+
export declare function resolveBarDomains(ext: {
|
|
124
|
+
maxVal: number;
|
|
125
|
+
minPos: number;
|
|
126
|
+
}, log: boolean): {
|
|
127
|
+
domain: [number, number];
|
|
128
|
+
tickValues: number[];
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* The value scale over a resolved domain — reconstructable by the
|
|
132
|
+
* session from the AST's domain alone.
|
|
133
|
+
* @param {[number, number]} domain @param {boolean} log
|
|
134
|
+
* @returns {(v: number) => number}
|
|
135
|
+
*/
|
|
136
|
+
export declare function barScale(domain: [number, number], log: boolean): (v: number) => number;
|
|
137
|
+
/**
|
|
138
|
+
* Build the geometry-free bar AST.
|
|
139
|
+
* @param {any} data
|
|
140
|
+
* @param {any} [config]
|
|
141
|
+
* @returns {BarAST}
|
|
142
|
+
*/
|
|
143
|
+
export declare function buildBarAST(data: any, config?: any): BarAST;
|
|
144
|
+
/**
|
|
145
|
+
* Render one bar as its `<rect>` value mark — the replaceable unit the
|
|
146
|
+
* incremental session re-emits when a live count changes.
|
|
147
|
+
* @param {BarMarkAST} bar
|
|
148
|
+
* @param {BarAST} ast
|
|
149
|
+
* @param {{x:number,y:number,w:number,h:number}} plot
|
|
150
|
+
* @param {{tokens: Record<string,string>}} theme
|
|
151
|
+
* @param {readonly string[]} palette
|
|
152
|
+
* @param {import('../core/marks.js').ChartTooltip|null} [tooltip]
|
|
153
|
+
* @returns {any}
|
|
154
|
+
*/
|
|
155
|
+
export declare function barMarkRender(bar: BarMarkAST, ast: BarAST, plot: {
|
|
156
|
+
x: number;
|
|
157
|
+
y: number;
|
|
158
|
+
w: number;
|
|
159
|
+
h: number;
|
|
160
|
+
}, theme: {
|
|
161
|
+
tokens: Record<string, string>;
|
|
162
|
+
}, palette: readonly string[], tooltip?: import('../core/marks.js').ChartTooltip | null): any;
|
|
163
|
+
/**
|
|
164
|
+
* Render a bar AST and return the svg WITH the geometry a session needs
|
|
165
|
+
* to replace one bar in place: the plot rect and how many chrome
|
|
166
|
+
* children precede the bars.
|
|
167
|
+
* @param {BarAST} ast
|
|
168
|
+
* @param {{tokens: Record<string,string>, cssVars: Record<string,string>}} theme
|
|
169
|
+
* @param {string} hash
|
|
170
|
+
* @param {{rootClass?: string, keyPrefix?: string, palette?: readonly string[], width?: number,
|
|
171
|
+
* tooltip?: import('../core/marks.js').ChartTooltipSpec}} [options]
|
|
172
|
+
* @returns {{svg: any, plot: {x:number,y:number,w:number,h:number}, chromeLen: number}}
|
|
173
|
+
*/
|
|
174
|
+
export declare function buildBarRender(ast: BarAST, theme: {
|
|
175
|
+
tokens: Record<string, string>;
|
|
176
|
+
cssVars: Record<string, string>;
|
|
177
|
+
}, hash: string, options?: {
|
|
178
|
+
rootClass?: string;
|
|
179
|
+
keyPrefix?: string;
|
|
180
|
+
palette?: readonly string[];
|
|
181
|
+
width?: number;
|
|
182
|
+
tooltip?: import('../core/marks.js').ChartTooltipSpec;
|
|
183
|
+
}): {
|
|
184
|
+
svg: any;
|
|
185
|
+
plot: {
|
|
186
|
+
x: number;
|
|
187
|
+
y: number;
|
|
188
|
+
w: number;
|
|
189
|
+
h: number;
|
|
190
|
+
};
|
|
191
|
+
chromeLen: number;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Render a bar AST to a pure-vnode SVG. Each bar rect carries a
|
|
195
|
+
* `<title>` naming its series, category and exact value — the axis
|
|
196
|
+
* shows the rounded tick scale, the hover text shows the datum.
|
|
197
|
+
* @param {BarAST} ast
|
|
198
|
+
* @param {{tokens: Record<string,string>, cssVars: Record<string,string>}} theme
|
|
199
|
+
* @param {string} hash
|
|
200
|
+
* @param {{rootClass?: string, keyPrefix?: string, palette?: readonly string[], width?: number,
|
|
201
|
+
* tooltip?: import('../core/marks.js').ChartTooltipSpec}} [options]
|
|
202
|
+
* @returns {any}
|
|
203
|
+
*/
|
|
204
|
+
export declare function renderBarAST(ast: BarAST, theme: {
|
|
205
|
+
tokens: Record<string, string>;
|
|
206
|
+
cssVars: Record<string, string>;
|
|
207
|
+
}, hash: string, options?: {
|
|
208
|
+
rootClass?: string;
|
|
209
|
+
keyPrefix?: string;
|
|
210
|
+
palette?: readonly string[];
|
|
211
|
+
width?: number;
|
|
212
|
+
tooltip?: import('../core/marks.js').ChartTooltipSpec;
|
|
213
|
+
}): any;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The boxplot chart type: five-number summaries per category with
|
|
3
|
+
* Tukey whiskers and outlier dots. Data shape (two forms per box):
|
|
4
|
+
*
|
|
5
|
+
* data = { boxes: [{ label, values: number[] } // raw samples
|
|
6
|
+
* | { label, min, q1, med, q3, max, outliers? }] } // precomputed
|
|
7
|
+
* config = { type:'boxplot', title?, catLabel?, valLabel? }
|
|
8
|
+
*
|
|
9
|
+
* Raw samples get the standard treatment: quartiles by linear
|
|
10
|
+
* interpolation over the sorted values, whiskers at the most extreme
|
|
11
|
+
* samples inside the 1.5·IQR fences, everything outside them an
|
|
12
|
+
* outlier. Precomputed summaries are trusted as given (their whiskers
|
|
13
|
+
* are the stated min/max). The AST is unit-space: `u` along the
|
|
14
|
+
* category axis, `v` along the value axis.
|
|
15
|
+
*/
|
|
16
|
+
export type BoxAST = {
|
|
17
|
+
label: string;
|
|
18
|
+
u0: number;
|
|
19
|
+
u1: number;
|
|
20
|
+
/**
|
|
21
|
+
* whisker low
|
|
22
|
+
*/
|
|
23
|
+
loV: number;
|
|
24
|
+
q1V: number;
|
|
25
|
+
medV: number;
|
|
26
|
+
q3V: number;
|
|
27
|
+
/**
|
|
28
|
+
* whisker high
|
|
29
|
+
*/
|
|
30
|
+
hiV: number;
|
|
31
|
+
outliersV: number[];
|
|
32
|
+
stats: {
|
|
33
|
+
min: number;
|
|
34
|
+
q1: number;
|
|
35
|
+
med: number;
|
|
36
|
+
q3: number;
|
|
37
|
+
max: number;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export type BoxplotAST = {
|
|
41
|
+
type: 'boxplot';
|
|
42
|
+
title: string | null;
|
|
43
|
+
cat: {
|
|
44
|
+
ticks: {
|
|
45
|
+
pos: number;
|
|
46
|
+
label: string;
|
|
47
|
+
}[];
|
|
48
|
+
label: string | null;
|
|
49
|
+
};
|
|
50
|
+
val: {
|
|
51
|
+
ticks: {
|
|
52
|
+
pos: number;
|
|
53
|
+
label: string;
|
|
54
|
+
}[];
|
|
55
|
+
label: string | null;
|
|
56
|
+
};
|
|
57
|
+
boxes: BoxAST[];
|
|
58
|
+
/**
|
|
59
|
+
* number of categories
|
|
60
|
+
*/
|
|
61
|
+
count: number;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* @typedef {object} BoxAST
|
|
65
|
+
* @property {string} label
|
|
66
|
+
* @property {number} u0 @property {number} u1
|
|
67
|
+
* @property {number} loV whisker low @property {number} q1V
|
|
68
|
+
* @property {number} medV @property {number} q3V
|
|
69
|
+
* @property {number} hiV whisker high
|
|
70
|
+
* @property {number[]} outliersV
|
|
71
|
+
* @property {{min:number, q1:number, med:number, q3:number, max:number}} stats
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* @typedef {object} BoxplotAST
|
|
75
|
+
* @property {'boxplot'} type
|
|
76
|
+
* @property {string|null} title
|
|
77
|
+
* @property {{ticks: {pos:number,label:string}[], label: string|null}} cat
|
|
78
|
+
* @property {{ticks: {pos:number,label:string}[], label: string|null}} val
|
|
79
|
+
* @property {BoxAST[]} boxes
|
|
80
|
+
* @property {number} count number of categories
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* Quantile of an ascending-sorted sample by linear interpolation.
|
|
84
|
+
* @param {number[]} sorted - Ascending finite samples (non-empty)
|
|
85
|
+
* @param {number} p - Quantile in [0, 1]
|
|
86
|
+
* @returns {number}
|
|
87
|
+
*/
|
|
88
|
+
export declare function quantileSorted(sorted: number[], p: number): number;
|
|
89
|
+
/**
|
|
90
|
+
* Build the geometry-free boxplot AST.
|
|
91
|
+
* @param {any} data
|
|
92
|
+
* @param {any} [config]
|
|
93
|
+
* @returns {BoxplotAST}
|
|
94
|
+
*/
|
|
95
|
+
export declare function buildBoxplotAST(data: any, config?: any): BoxplotAST;
|
|
96
|
+
/**
|
|
97
|
+
* Render a boxplot AST to a pure-vnode SVG: capped whiskers, a
|
|
98
|
+
* translucent box with a full-strength median line, outlier dots, and
|
|
99
|
+
* a summary `<title>` per box.
|
|
100
|
+
* @param {BoxplotAST} ast
|
|
101
|
+
* @param {{tokens: Record<string,string>, cssVars: Record<string,string>}} theme
|
|
102
|
+
* @param {string} hash
|
|
103
|
+
* @param {{rootClass?: string, keyPrefix?: string, palette?: readonly string[], width?: number,
|
|
104
|
+
* tooltip?: import('../core/marks.js').ChartTooltipSpec}} [options]
|
|
105
|
+
* @returns {any}
|
|
106
|
+
*/
|
|
107
|
+
export declare function renderBoxplotAST(ast: BoxplotAST, theme: {
|
|
108
|
+
tokens: Record<string, string>;
|
|
109
|
+
cssVars: Record<string, string>;
|
|
110
|
+
}, hash: string, options?: {
|
|
111
|
+
rootClass?: string;
|
|
112
|
+
keyPrefix?: string;
|
|
113
|
+
palette?: readonly string[];
|
|
114
|
+
width?: number;
|
|
115
|
+
tooltip?: import('../core/marks.js').ChartTooltipSpec;
|
|
116
|
+
}): any;
|