@galaxy-io/dls 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts/BarChart.d.ts +3 -3
- package/dist/charts/BarChart.js +68 -104
- package/dist/charts/ChartCategoryTargets.d.ts +27 -0
- package/dist/charts/ChartCategoryTargets.js +75 -0
- package/dist/charts/ChartFrame.d.ts +34 -6
- package/dist/charts/ChartFrame.js +72 -15
- package/dist/charts/ChartPrimitives.d.ts +35 -0
- package/dist/charts/ChartPrimitives.js +75 -38
- package/dist/charts/ChartTooltip.d.ts +3 -3
- package/dist/charts/ChartTooltip.js +2 -2
- package/dist/charts/LineChart.js +47 -62
- package/dist/charts/PieChart.js +48 -26
- package/dist/charts/barChartGeometry.d.ts +66 -33
- package/dist/charts/barChartGeometry.js +7 -15
- package/dist/charts/barChartLegend.d.ts +25 -0
- package/dist/charts/barChartLegend.js +23 -0
- package/dist/charts/chartFormat.d.ts +9 -1
- package/dist/charts/chartFormat.js +13 -1
- package/dist/charts/chartScales.d.ts +58 -22
- package/dist/charts/chartScales.js +92 -38
- package/dist/charts/constants.d.ts +22 -6
- package/dist/charts/constants.js +22 -1
- package/dist/charts/lineChartGeometry.d.ts +53 -15
- package/dist/charts/lineChartGeometry.js +6 -15
- package/dist/charts/pieChartGeometry.d.ts +20 -8
- package/dist/charts/pieChartGeometry.js +3 -13
- package/dist/charts/types.d.ts +51 -145
- package/dist/charts/types.js +22 -3
- package/dist/charts/useCartesianChartLayout.d.ts +70 -0
- package/dist/charts/useCartesianChartLayout.js +56 -0
- package/dist/charts/useChartDimensions.d.ts +10 -3
- package/dist/charts/useChartDimensions.js +14 -4
- package/dist/charts/useChartInteraction.d.ts +13 -8
- package/dist/charts/useChartInteraction.js +7 -11
- package/dist/charts/useSeriesColorResolver.d.ts +37 -0
- package/dist/charts/useSeriesColorResolver.js +27 -0
- package/dist/styles.css +13 -11
- package/package.json +1 -1
|
@@ -154,13 +154,10 @@ export declare const PIE_TOOLTIP_ANCHOR_INSET = 8;
|
|
|
154
154
|
* them communicates more than rendering each faithfully.
|
|
155
155
|
*/
|
|
156
156
|
export declare const PIE_MIN_SLICE_SHARE = 0.02;
|
|
157
|
+
/** React key used for the bucket that absorbs slices below the fold threshold. */
|
|
158
|
+
export declare const AGGREGATED_SLICE_KEY = "__other__";
|
|
157
159
|
/** Margin around a pie, which needs no axis gutters. */
|
|
158
|
-
export declare const PIE_CHART_MARGIN:
|
|
159
|
-
top: number;
|
|
160
|
-
right: number;
|
|
161
|
-
bottom: number;
|
|
162
|
-
left: number;
|
|
163
|
-
};
|
|
160
|
+
export declare const PIE_CHART_MARGIN: ChartMargin;
|
|
164
161
|
/**
|
|
165
162
|
* Duration in ms for hover, dim and tooltip transitions.
|
|
166
163
|
*
|
|
@@ -218,6 +215,25 @@ export declare const CHART_TOOLTIP_MAX_WIDTH = 320;
|
|
|
218
215
|
export declare const CAPTION_CHAR_WIDTH_PX = 6.2;
|
|
219
216
|
/** Ceiling for an auto-sized left margin, so a wide formatter can't eat the plot. */
|
|
220
217
|
export declare const MAX_AUTO_MARGIN_LEFT = 96;
|
|
218
|
+
/**
|
|
219
|
+
* Floor for an auto-sized left margin.
|
|
220
|
+
*
|
|
221
|
+
* Enough for a two- or three-character tick plus {@link VALUE_AXIS_TICK_GAP}, so
|
|
222
|
+
* an axis labelled `0`–`5` still has its numbers clear of the container edge
|
|
223
|
+
* rather than jammed against it.
|
|
224
|
+
*/
|
|
225
|
+
export declare const MIN_AUTO_MARGIN_LEFT = 32;
|
|
226
|
+
/**
|
|
227
|
+
* Quantum for an auto-sized left margin, in px.
|
|
228
|
+
*
|
|
229
|
+
* Sizing the gutter to the widest tick means the plot origin moves whenever that
|
|
230
|
+
* label's width changes — live data crossing 999 → 1000 gains a digit and would
|
|
231
|
+
* shift every mark sideways. Rounding up to a step absorbs that: the margin only
|
|
232
|
+
* moves when a label crosses a real threshold, and two charts with similar ticks
|
|
233
|
+
* land on the *same* value, so stacked charts in a dashboard keep their plots
|
|
234
|
+
* aligned instead of each choosing its own origin.
|
|
235
|
+
*/
|
|
236
|
+
export declare const AUTO_MARGIN_LEFT_STEP = 8;
|
|
221
237
|
/** Minimum px between category labels before AUTO mode starts skipping them. */
|
|
222
238
|
export declare const MIN_CATEGORY_LABEL_GAP = 8;
|
|
223
239
|
/**
|
package/dist/charts/constants.js
CHANGED
|
@@ -159,6 +159,8 @@ var PIE_TOOLTIP_ANCHOR_INSET = 8;
|
|
|
159
159
|
* them communicates more than rendering each faithfully.
|
|
160
160
|
*/
|
|
161
161
|
var PIE_MIN_SLICE_SHARE = .02;
|
|
162
|
+
/** React key used for the bucket that absorbs slices below the fold threshold. */
|
|
163
|
+
var AGGREGATED_SLICE_KEY = "__other__";
|
|
162
164
|
/** Margin around a pie, which needs no axis gutters. */
|
|
163
165
|
var PIE_CHART_MARGIN = {
|
|
164
166
|
top: 8,
|
|
@@ -223,6 +225,25 @@ var CHART_TOOLTIP_MAX_WIDTH = 320;
|
|
|
223
225
|
var CAPTION_CHAR_WIDTH_PX = 6.2;
|
|
224
226
|
/** Ceiling for an auto-sized left margin, so a wide formatter can't eat the plot. */
|
|
225
227
|
var MAX_AUTO_MARGIN_LEFT = 96;
|
|
228
|
+
/**
|
|
229
|
+
* Floor for an auto-sized left margin.
|
|
230
|
+
*
|
|
231
|
+
* Enough for a two- or three-character tick plus {@link VALUE_AXIS_TICK_GAP}, so
|
|
232
|
+
* an axis labelled `0`–`5` still has its numbers clear of the container edge
|
|
233
|
+
* rather than jammed against it.
|
|
234
|
+
*/
|
|
235
|
+
var MIN_AUTO_MARGIN_LEFT = 32;
|
|
236
|
+
/**
|
|
237
|
+
* Quantum for an auto-sized left margin, in px.
|
|
238
|
+
*
|
|
239
|
+
* Sizing the gutter to the widest tick means the plot origin moves whenever that
|
|
240
|
+
* label's width changes — live data crossing 999 → 1000 gains a digit and would
|
|
241
|
+
* shift every mark sideways. Rounding up to a step absorbs that: the margin only
|
|
242
|
+
* moves when a label crosses a real threshold, and two charts with similar ticks
|
|
243
|
+
* land on the *same* value, so stacked charts in a dashboard keep their plots
|
|
244
|
+
* aligned instead of each choosing its own origin.
|
|
245
|
+
*/
|
|
246
|
+
var AUTO_MARGIN_LEFT_STEP = 8;
|
|
226
247
|
/** Minimum px between category labels before AUTO mode starts skipping them. */
|
|
227
248
|
var MIN_CATEGORY_LABEL_GAP = 8;
|
|
228
249
|
/**
|
|
@@ -243,4 +264,4 @@ var CHART_PALETTE_ORDER = [
|
|
|
243
264
|
ChartPalette.RED
|
|
244
265
|
];
|
|
245
266
|
//#endregion
|
|
246
|
-
export { AXIS_TITLE_BAND, AXIS_TITLE_GAP, BAR_GAP_COMFORTABLE, BAR_GAP_MEDIUM, BAR_GAP_TIGHT, BAR_RADIUS, BAR_RADIUS_NARROW, BAR_WIDTH_RATIO, CAPTION_CHAR_WIDTH_PX, CATEGORY_AXIS_LABEL_GAP, CATEGORY_AXIS_LABEL_HEIGHT, CHART_MARK_OPACITY_ACTIVE, CHART_MARK_OPACITY_FADED, CHART_MARK_OPACITY_MUTED, CHART_PALETTE_ORDER, CHART_RESTORE_DELAY_MS, CHART_TOOLTIP_MAX_WIDTH, CHART_TOOLTIP_MIN_WIDTH, CHART_TOOLTIP_OFFSET, CHART_TRANSITION_MS, DEFAULT_CHART_MARGIN, DEFAULT_LINE_STROKE_WIDTH, DEFAULT_VALUE_TICK_COUNT, GRID_LINE_BLEED, GROUP_GAP_COMFORTABLE, GROUP_GAP_MEDIUM, GROUP_GAP_TIGHT, LINE_AREA_OPACITY, LINE_POINT_RADIUS, MAX_AUTO_MARGIN_LEFT, MAX_BAR_WIDTH, MAX_GAP_SHARE, MIN_BARS_FOR_TIGHT_SPACING, MIN_BAR_LENGTH, MIN_CATEGORY_LABEL_GAP, NARROW_BAR_WIDTH, PIE_CHART_MARGIN, PIE_CORNER_RADIUS, PIE_DONUT_INNER_RATIO, PIE_MAX_AUTO_INNER_RATIO, PIE_MAX_INSET_SHARE, PIE_MIN_SLICE_SHARE, PIE_PAD_ANGLE, PIE_TOOLTIP_ANCHOR_INSET, STACK_SEGMENT_GAP, VALUE_AXIS_LABEL_HEIGHT, VALUE_AXIS_TICK_GAP, WIDTH_FOR_MEDIUM_SPACING, WIDTH_FOR_TIGHT_SPACING };
|
|
267
|
+
export { AGGREGATED_SLICE_KEY, AUTO_MARGIN_LEFT_STEP, AXIS_TITLE_BAND, AXIS_TITLE_GAP, BAR_GAP_COMFORTABLE, BAR_GAP_MEDIUM, BAR_GAP_TIGHT, BAR_RADIUS, BAR_RADIUS_NARROW, BAR_WIDTH_RATIO, CAPTION_CHAR_WIDTH_PX, CATEGORY_AXIS_LABEL_GAP, CATEGORY_AXIS_LABEL_HEIGHT, CHART_MARK_OPACITY_ACTIVE, CHART_MARK_OPACITY_FADED, CHART_MARK_OPACITY_MUTED, CHART_PALETTE_ORDER, CHART_RESTORE_DELAY_MS, CHART_TOOLTIP_MAX_WIDTH, CHART_TOOLTIP_MIN_WIDTH, CHART_TOOLTIP_OFFSET, CHART_TRANSITION_MS, DEFAULT_CHART_MARGIN, DEFAULT_LINE_STROKE_WIDTH, DEFAULT_VALUE_TICK_COUNT, GRID_LINE_BLEED, GROUP_GAP_COMFORTABLE, GROUP_GAP_MEDIUM, GROUP_GAP_TIGHT, LINE_AREA_OPACITY, LINE_POINT_RADIUS, MAX_AUTO_MARGIN_LEFT, MAX_BAR_WIDTH, MAX_GAP_SHARE, MIN_AUTO_MARGIN_LEFT, MIN_BARS_FOR_TIGHT_SPACING, MIN_BAR_LENGTH, MIN_CATEGORY_LABEL_GAP, NARROW_BAR_WIDTH, PIE_CHART_MARGIN, PIE_CORNER_RADIUS, PIE_DONUT_INNER_RATIO, PIE_MAX_AUTO_INNER_RATIO, PIE_MAX_INSET_SHARE, PIE_MIN_SLICE_SHARE, PIE_PAD_ANGLE, PIE_TOOLTIP_ANCHOR_INSET, STACK_SEGMENT_GAP, VALUE_AXIS_LABEL_HEIGHT, VALUE_AXIS_TICK_GAP, WIDTH_FOR_MEDIUM_SPACING, WIDTH_FOR_TIGHT_SPACING };
|
|
@@ -1,17 +1,51 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildValueScale } from "./chartScales";
|
|
2
2
|
import { LineChartCurve } from "./types";
|
|
3
|
-
import type {
|
|
3
|
+
import type { LineChartLineDatum } from "./types";
|
|
4
|
+
/** Signed value domain across every line, ignoring gaps. */
|
|
5
|
+
export declare function getLineValueDomain<TMetric extends string>(lines: LineChartLineDatum<TMetric>[]): [number, number];
|
|
6
|
+
/** One line, resolved to SVG paths. */
|
|
7
|
+
export interface LineChartPath<TMetric extends string> {
|
|
8
|
+
/** React key. Equal to the metric, which is unique by construction. */
|
|
9
|
+
id: string;
|
|
10
|
+
metric: TMetric;
|
|
11
|
+
/** `d` for the stroke. Empty when the line has no plottable points. */
|
|
12
|
+
path: string;
|
|
13
|
+
/** `d` for the area fill. Present only when the line opted into an area. */
|
|
14
|
+
areaPath?: string;
|
|
15
|
+
/** Pre-serialised `stroke-dasharray`. Absent for a solid line. */
|
|
16
|
+
dashArray?: string;
|
|
17
|
+
strokeWidth: number;
|
|
18
|
+
color: string;
|
|
19
|
+
}
|
|
20
|
+
/** One point, resolved to pixels. */
|
|
21
|
+
export interface LineChartPoint<TMetric extends string> {
|
|
22
|
+
/** React key. `${metric}:${categoryIndex}`. */
|
|
23
|
+
id: string;
|
|
24
|
+
metric: TMetric;
|
|
25
|
+
value: number;
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
color: string;
|
|
29
|
+
}
|
|
4
30
|
/**
|
|
5
|
-
*
|
|
31
|
+
* One category column: the hit target and everything the tooltip needs.
|
|
6
32
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* the data is gappy — inferring order from a union of incomplete series is
|
|
10
|
-
* guesswork, and guessing wrong reorders time.
|
|
33
|
+
* Line charts hit-test by column rather than by proximity to a stroke, so the
|
|
34
|
+
* whole vertical band is a target and the tooltip reports every line at once.
|
|
11
35
|
*/
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
36
|
+
export interface LineChartColumn<TMetric extends string> {
|
|
37
|
+
categoryIndex: number;
|
|
38
|
+
label: string;
|
|
39
|
+
/** x of the category tick. */
|
|
40
|
+
x: number;
|
|
41
|
+
/** Full-height hit target, tiling with its neighbours. */
|
|
42
|
+
bandX: number;
|
|
43
|
+
bandWidth: number;
|
|
44
|
+
/** Points present in this column, one per line that has a value here. */
|
|
45
|
+
points: LineChartPoint<TMetric>[];
|
|
46
|
+
/** Topmost point in the column — where the tooltip anchors. */
|
|
47
|
+
anchorY: number;
|
|
48
|
+
}
|
|
15
49
|
export interface LineChartGeometry<TMetric extends string> {
|
|
16
50
|
paths: LineChartPath<TMetric>[];
|
|
17
51
|
columns: LineChartColumn<TMetric>[];
|
|
@@ -25,8 +59,6 @@ export interface LineChartGeometry<TMetric extends string> {
|
|
|
25
59
|
isolatedPoints: LineChartPoint<TMetric>[];
|
|
26
60
|
categories: string[];
|
|
27
61
|
valueScale: ReturnType<typeof buildValueScale>;
|
|
28
|
-
categoryScale: ReturnType<typeof buildCategoryPointScale>;
|
|
29
|
-
baselineY: number;
|
|
30
62
|
/**
|
|
31
63
|
* Distance between category ticks.
|
|
32
64
|
*
|
|
@@ -43,12 +75,18 @@ interface BuildLineChartGeometryArgs<TMetric extends string> {
|
|
|
43
75
|
plotWidth: number;
|
|
44
76
|
plotHeight: number;
|
|
45
77
|
curve: LineChartCurve;
|
|
46
|
-
|
|
78
|
+
/**
|
|
79
|
+
* The final value domain, already overridden, zeroed and niced.
|
|
80
|
+
*
|
|
81
|
+
* Resolved by the caller rather than here, because the left gutter is sized
|
|
82
|
+
* from the tick labels and therefore needs the domain before the plot — and
|
|
83
|
+
* hence this builder — exists.
|
|
84
|
+
*/
|
|
85
|
+
domain: [number, number];
|
|
47
86
|
strokeWidth?: number;
|
|
48
87
|
resolveColor: (args: {
|
|
49
88
|
metric: TMetric;
|
|
50
|
-
lineIndex: number;
|
|
51
89
|
}) => string;
|
|
52
90
|
}
|
|
53
|
-
export declare function buildLineChartGeometry<TMetric extends string>({ lines, categories: explicitCategories, plotWidth, plotHeight, curve,
|
|
91
|
+
export declare function buildLineChartGeometry<TMetric extends string>({ lines, categories: explicitCategories, plotWidth, plotHeight, curve, domain, strokeWidth: defaultStrokeWidth, resolveColor, }: BuildLineChartGeometryArgs<TMetric>): LineChartGeometry<TMetric>;
|
|
54
92
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LineChartCurve } from "./types.js";
|
|
2
2
|
import { DEFAULT_LINE_STROKE_WIDTH } from "./constants.js";
|
|
3
|
-
import {
|
|
3
|
+
import { buildCategoryPointScale, buildValueScale, sanitizeValue } from "./chartScales.js";
|
|
4
4
|
import { match } from "ts-pattern";
|
|
5
5
|
import { area, curveLinear, curveMonotoneX, curveStepAfter, line } from "d3-shape";
|
|
6
6
|
//#region src/charts/lineChartGeometry.ts
|
|
@@ -44,9 +44,9 @@ function getLineValueDomain(lines) {
|
|
|
44
44
|
}
|
|
45
45
|
return [Math.min(0, min), Math.max(0, max)];
|
|
46
46
|
}
|
|
47
|
-
function buildLineChartGeometry({ lines, categories: explicitCategories, plotWidth, plotHeight, curve,
|
|
47
|
+
function buildLineChartGeometry({ lines, categories: explicitCategories, plotWidth, plotHeight, curve, domain, strokeWidth: defaultStrokeWidth = DEFAULT_LINE_STROKE_WIDTH, resolveColor }) {
|
|
48
48
|
const categories = getLineCategories(lines, explicitCategories);
|
|
49
|
-
const valueScale = buildValueScale(
|
|
49
|
+
const valueScale = buildValueScale(domain, [plotHeight, 0]);
|
|
50
50
|
const categoryScale = buildCategoryPointScale(categories, [0, plotWidth]);
|
|
51
51
|
const baselineY = valueScale(0);
|
|
52
52
|
const paths = [];
|
|
@@ -58,19 +58,14 @@ function buildLineChartGeometry({ lines, categories: explicitCategories, plotWid
|
|
|
58
58
|
isolatedPoints,
|
|
59
59
|
categories,
|
|
60
60
|
valueScale,
|
|
61
|
-
categoryScale,
|
|
62
|
-
baselineY,
|
|
63
61
|
step: 0
|
|
64
62
|
};
|
|
65
63
|
const curveFactory = resolveCurve(curve);
|
|
66
64
|
const categoryIndex = new Map(categories.map((label, index) => [label, index]));
|
|
67
65
|
const xAt = (index) => categoryScale(categories[index]) ?? 0;
|
|
68
66
|
const pointsByCategory = categories.map(() => []);
|
|
69
|
-
lines.forEach((lineDatum
|
|
70
|
-
const color = resolveColor({
|
|
71
|
-
metric: lineDatum.metric,
|
|
72
|
-
lineIndex
|
|
73
|
-
});
|
|
67
|
+
lines.forEach((lineDatum) => {
|
|
68
|
+
const color = resolveColor({ metric: lineDatum.metric });
|
|
74
69
|
const stroke = lineDatum.strokeWidth ?? defaultStrokeWidth;
|
|
75
70
|
const plotted = categories.map((_, index) => ({
|
|
76
71
|
categoryIndex: index,
|
|
@@ -87,7 +82,6 @@ function buildLineChartGeometry({ lines, categories: explicitCategories, plotWid
|
|
|
87
82
|
paths.push({
|
|
88
83
|
id: lineDatum.metric,
|
|
89
84
|
metric: lineDatum.metric,
|
|
90
|
-
lineIndex,
|
|
91
85
|
path: strokePath,
|
|
92
86
|
areaPath,
|
|
93
87
|
dashArray: lineDatum.dashSize ? `${lineDatum.dashSize} ${lineDatum.dashSize}` : void 0,
|
|
@@ -99,7 +93,6 @@ function buildLineChartGeometry({ lines, categories: explicitCategories, plotWid
|
|
|
99
93
|
const point = {
|
|
100
94
|
id: `${lineDatum.metric}:${p.categoryIndex}`,
|
|
101
95
|
metric: lineDatum.metric,
|
|
102
|
-
categoryIndex: p.categoryIndex,
|
|
103
96
|
value: p.value,
|
|
104
97
|
x: xAt(p.categoryIndex),
|
|
105
98
|
y: valueScale(p.value),
|
|
@@ -134,10 +127,8 @@ function buildLineChartGeometry({ lines, categories: explicitCategories, plotWid
|
|
|
134
127
|
isolatedPoints,
|
|
135
128
|
categories,
|
|
136
129
|
valueScale,
|
|
137
|
-
categoryScale,
|
|
138
|
-
baselineY,
|
|
139
130
|
step
|
|
140
131
|
};
|
|
141
132
|
}
|
|
142
133
|
//#endregion
|
|
143
|
-
export { buildLineChartGeometry,
|
|
134
|
+
export { buildLineChartGeometry, getLineValueDomain };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChartPalette,
|
|
1
|
+
import type { ChartPalette, PieChartSliceDatum } from "./types";
|
|
2
2
|
/**
|
|
3
3
|
* Pie and donut geometry.
|
|
4
4
|
*
|
|
@@ -7,14 +7,27 @@ import type { ChartPalette, PieChartArc, PieChartSliceDatum } from "./types";
|
|
|
7
7
|
*
|
|
8
8
|
* Pure: no React, no theme access. Colours arrive through a resolver callback.
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
|
|
10
|
+
/** One rendered arc. */
|
|
11
|
+
export interface PieChartArc {
|
|
12
|
+
/** React key. The slice key, or `AGGREGATED_SLICE_KEY` for the folded bucket. */
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
/** Summed value for the aggregated bucket, the slice's own otherwise. */
|
|
16
|
+
value: number;
|
|
17
|
+
/** Share of the total, 0–1. */
|
|
18
|
+
share: number;
|
|
19
|
+
/** `d` for the arc. */
|
|
20
|
+
path: string;
|
|
21
|
+
/** Anchor for the tooltip, just outside the arc's outer edge. */
|
|
22
|
+
anchorX: number;
|
|
23
|
+
anchorY: number;
|
|
24
|
+
color: string;
|
|
25
|
+
}
|
|
26
|
+
export interface PieChartGeometry {
|
|
27
|
+
arcs: PieChartArc[];
|
|
14
28
|
/** Centre of the pie, in plot coordinates. */
|
|
15
29
|
centerX: number;
|
|
16
30
|
centerY: number;
|
|
17
|
-
outerRadius: number;
|
|
18
31
|
innerRadius: number;
|
|
19
32
|
}
|
|
20
33
|
interface BuildPieChartGeometryArgs<TSlice extends string> {
|
|
@@ -37,12 +50,11 @@ interface BuildPieChartGeometryArgs<TSlice extends string> {
|
|
|
37
50
|
aggregatedLabel?: string;
|
|
38
51
|
resolveColor: (args: {
|
|
39
52
|
sliceKey: TSlice | null;
|
|
40
|
-
index: number;
|
|
41
53
|
explicit?: ChartPalette;
|
|
42
54
|
}) => string;
|
|
43
55
|
/** Palette override declared by the caller for a given slice. */
|
|
44
56
|
getSliceColor?: (sliceKey: TSlice) => ChartPalette | undefined;
|
|
45
57
|
getSliceLabel: (sliceKey: TSlice) => string;
|
|
46
58
|
}
|
|
47
|
-
export declare function buildPieChartGeometry<TSlice extends string>({ slices, plotWidth, plotHeight, innerRadiusRatio, padAngle, cornerRadius, minSliceShare, aggregatedLabel, resolveColor, getSliceColor, getSliceLabel, }: BuildPieChartGeometryArgs<TSlice>): PieChartGeometry
|
|
59
|
+
export declare function buildPieChartGeometry<TSlice extends string>({ slices, plotWidth, plotHeight, innerRadiusRatio, padAngle, cornerRadius, minSliceShare, aggregatedLabel, resolveColor, getSliceColor, getSliceLabel, }: BuildPieChartGeometryArgs<TSlice>): PieChartGeometry;
|
|
48
60
|
export {};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AGGREGATED_SLICE_KEY } from "./
|
|
2
|
-
import { PIE_DONUT_INNER_RATIO, PIE_MAX_AUTO_INNER_RATIO, PIE_MAX_INSET_SHARE, PIE_PAD_ANGLE } from "./constants.js";
|
|
1
|
+
import { AGGREGATED_SLICE_KEY, PIE_DONUT_INNER_RATIO, PIE_MAX_AUTO_INNER_RATIO, PIE_MAX_INSET_SHARE, PIE_PAD_ANGLE } from "./constants.js";
|
|
3
2
|
import { sanitizeValue } from "./chartScales.js";
|
|
4
3
|
import { arc, pie } from "d3-shape";
|
|
5
4
|
//#region src/charts/pieChartGeometry.ts
|
|
@@ -16,10 +15,8 @@ function buildPieChartGeometry({ slices, plotWidth, plotHeight, innerRadiusRatio
|
|
|
16
15
|
const total = sanitized.reduce((sum, slice) => sum + slice.value, 0);
|
|
17
16
|
const empty = {
|
|
18
17
|
arcs: [],
|
|
19
|
-
total,
|
|
20
18
|
centerX,
|
|
21
19
|
centerY,
|
|
22
|
-
outerRadius,
|
|
23
20
|
innerRadius: requestedInnerRadius
|
|
24
21
|
};
|
|
25
22
|
if (total <= 0 || outerRadius <= 0) return empty;
|
|
@@ -51,13 +48,12 @@ function buildPieChartGeometry({ slices, plotWidth, plotHeight, innerRadiusRatio
|
|
|
51
48
|
const layout = pie().sort(null).value((slice) => slice.value).padAngle(padAngle);
|
|
52
49
|
const arcGenerator = arc().innerRadius(innerRadius).outerRadius(outerRadius).cornerRadius(cornerRadius);
|
|
53
50
|
return {
|
|
54
|
-
arcs: layout(kept).map((slot
|
|
51
|
+
arcs: layout(kept).map((slot) => {
|
|
55
52
|
const slice = slot.data;
|
|
56
53
|
const midAngle = (slot.startAngle + slot.endAngle) / 2;
|
|
57
54
|
const anchorRadius = outerRadius + 8;
|
|
58
55
|
return {
|
|
59
56
|
id: slice.isAggregated ? AGGREGATED_SLICE_KEY : slice.sliceKey,
|
|
60
|
-
sliceKey: slice.sliceKey,
|
|
61
57
|
label: slice.label,
|
|
62
58
|
value: slice.value,
|
|
63
59
|
share: slice.value / total,
|
|
@@ -66,22 +62,16 @@ function buildPieChartGeometry({ slices, plotWidth, plotHeight, innerRadiusRatio
|
|
|
66
62
|
endAngle: slot.endAngle,
|
|
67
63
|
padAngle: slot.padAngle
|
|
68
64
|
}) ?? "",
|
|
69
|
-
startAngle: slot.startAngle,
|
|
70
|
-
endAngle: slot.endAngle,
|
|
71
65
|
anchorX: centerX + Math.sin(midAngle) * anchorRadius,
|
|
72
66
|
anchorY: centerY - Math.cos(midAngle) * anchorRadius,
|
|
73
67
|
color: resolveColor({
|
|
74
68
|
sliceKey: slice.sliceKey,
|
|
75
|
-
index,
|
|
76
69
|
explicit: slice.explicit
|
|
77
|
-
})
|
|
78
|
-
isAggregated: slice.isAggregated
|
|
70
|
+
})
|
|
79
71
|
};
|
|
80
72
|
}),
|
|
81
|
-
total,
|
|
82
73
|
centerX,
|
|
83
74
|
centerY,
|
|
84
|
-
outerRadius,
|
|
85
75
|
innerRadius
|
|
86
76
|
};
|
|
87
77
|
}
|
package/dist/charts/types.d.ts
CHANGED
|
@@ -108,6 +108,18 @@ export interface ChartValueDomain {
|
|
|
108
108
|
/** Approximate tick count passed to d3's `scale.ticks()`. */
|
|
109
109
|
tickCount: number;
|
|
110
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Which chart is being rendered.
|
|
113
|
+
*
|
|
114
|
+
* Exists so the frame can phrase a default accessible name — a pie has slices
|
|
115
|
+
* where the cartesian charts have categories. Deliberately not a styling hook:
|
|
116
|
+
* nothing else branches on it.
|
|
117
|
+
*/
|
|
118
|
+
export declare enum ChartKind {
|
|
119
|
+
BAR = "BAR",
|
|
120
|
+
LINE = "LINE",
|
|
121
|
+
PIE = "PIE"
|
|
122
|
+
}
|
|
111
123
|
/** How the category axis copes when labels outgrow their slots. */
|
|
112
124
|
export declare enum ChartCategoryLabelMode {
|
|
113
125
|
/** Render every label that fits; otherwise show every nth. The default. */
|
|
@@ -175,83 +187,20 @@ export interface BarChartComponentDatum<TComponentKey extends string = string> {
|
|
|
175
187
|
/**
|
|
176
188
|
* One bar within a group: a stack of components for a single metric.
|
|
177
189
|
*/
|
|
178
|
-
export interface BarChartBarDatum<TMetric extends string,
|
|
190
|
+
export interface BarChartBarDatum<TMetric extends string, TComponentKey extends string = string> {
|
|
179
191
|
/** Which metric this bar represents, e.g. `"prospected"`. */
|
|
180
192
|
metric: TMetric;
|
|
181
|
-
/** Optional dimension the bar is split by, e.g. `"persona"`. */
|
|
182
|
-
pivot?: TPivot;
|
|
183
193
|
/** Segments of the bar, stacked in array order outward from the baseline. */
|
|
184
194
|
components: BarChartComponentDatum<TComponentKey>[];
|
|
185
195
|
}
|
|
186
196
|
/**
|
|
187
197
|
* One category on the x-axis, holding one bar per metric.
|
|
188
198
|
*/
|
|
189
|
-
export interface BarChartGroupDatum<TMetric extends string,
|
|
199
|
+
export interface BarChartGroupDatum<TMetric extends string, TComponentKey extends string = string> {
|
|
190
200
|
/** Label rendered beneath this group on the category axis. */
|
|
191
201
|
label: string;
|
|
192
202
|
/** Bars in this group, rendered left to right in array order. */
|
|
193
|
-
bars: BarChartBarDatum<TMetric,
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* A single rendered rectangle.
|
|
197
|
-
*
|
|
198
|
-
* The geometry layer flattens the group/bar/component hierarchy into an array
|
|
199
|
-
* of these, so rendering is a plain `.map()` with no nested loops or
|
|
200
|
-
* accumulators in the component body.
|
|
201
|
-
*/
|
|
202
|
-
export interface BarChartRect<TMetric extends string, TComponentKey extends string = string> {
|
|
203
|
-
/**
|
|
204
|
-
* React key: `${groupIndex}:${barIndex}:${componentKey}`.
|
|
205
|
-
*
|
|
206
|
-
* Deliberately index-based rather than label-based — group labels are free to
|
|
207
|
-
* repeat, and duplicated keys would silently drop rectangles.
|
|
208
|
-
*/
|
|
209
|
-
id: string;
|
|
210
|
-
groupIndex: number;
|
|
211
|
-
barIndex: number;
|
|
212
|
-
metric: TMetric;
|
|
213
|
-
componentKey: TComponentKey;
|
|
214
|
-
/** The component's label, carried through for the tooltip. */
|
|
215
|
-
label: string;
|
|
216
|
-
/** The raw value, before any normalization. */
|
|
217
|
-
value: number;
|
|
218
|
-
/**
|
|
219
|
-
* The `[from, to]` interval this segment occupies in value space.
|
|
220
|
-
* Under {@link BarChartNormalization.PERCENT} this is normalized to 0–1.
|
|
221
|
-
*/
|
|
222
|
-
valueRange: [number, number];
|
|
223
|
-
x: number;
|
|
224
|
-
y: number;
|
|
225
|
-
width: number;
|
|
226
|
-
height: number;
|
|
227
|
-
/** Resolved from the theme — never a raw hex from consumer data. */
|
|
228
|
-
color: string;
|
|
229
|
-
/** Interior stack segments get {@link BarCorners.NONE}. */
|
|
230
|
-
corners: BarCorners;
|
|
231
|
-
/** Corner radius in px, reduced for narrow bars so the curve can't dominate. */
|
|
232
|
-
radius: number;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* A category's invisible hit target and tooltip anchor.
|
|
236
|
-
*
|
|
237
|
-
* Hit testing happens per group rather than per rectangle: a two-pixel bar is
|
|
238
|
-
* then exactly as hoverable as a two-hundred-pixel one, and moving the pointer
|
|
239
|
-
* between segments inside one group fires nothing, so the tooltip stays put
|
|
240
|
-
* instead of jumping between segment tops.
|
|
241
|
-
*/
|
|
242
|
-
export interface BarChartGroupBand {
|
|
243
|
-
groupIndex: number;
|
|
244
|
-
label: string;
|
|
245
|
-
/** Tiles edge to edge with its neighbours, so there are no dead gutters. */
|
|
246
|
-
x: number;
|
|
247
|
-
y: number;
|
|
248
|
-
width: number;
|
|
249
|
-
height: number;
|
|
250
|
-
/** Group centre, at the top of its tallest bar. Stable while hovering. */
|
|
251
|
-
anchorX: number;
|
|
252
|
-
anchorY: number;
|
|
253
|
-
/** True when every component in the group is zero or absent. */
|
|
254
|
-
isEmpty: boolean;
|
|
203
|
+
bars: BarChartBarDatum<TMetric, TComponentKey>[];
|
|
255
204
|
}
|
|
256
205
|
/** How the segments between points are interpolated. */
|
|
257
206
|
export declare enum LineChartCurve {
|
|
@@ -299,51 +248,6 @@ export interface LineChartLineDatum<TMetric extends string> {
|
|
|
299
248
|
/** Fill the area between the line and the baseline. */
|
|
300
249
|
showArea?: boolean;
|
|
301
250
|
}
|
|
302
|
-
/** One line, resolved to SVG paths. */
|
|
303
|
-
export interface LineChartPath<TMetric extends string> {
|
|
304
|
-
/** React key. Equal to the metric, which is unique by construction. */
|
|
305
|
-
id: string;
|
|
306
|
-
metric: TMetric;
|
|
307
|
-
lineIndex: number;
|
|
308
|
-
/** `d` for the stroke. Empty when the line has no plottable points. */
|
|
309
|
-
path: string;
|
|
310
|
-
/** `d` for the area fill. Present only when the line opted into an area. */
|
|
311
|
-
areaPath?: string;
|
|
312
|
-
/** Pre-serialised `stroke-dasharray`. Absent for a solid line. */
|
|
313
|
-
dashArray?: string;
|
|
314
|
-
strokeWidth: number;
|
|
315
|
-
color: string;
|
|
316
|
-
}
|
|
317
|
-
/** One point, resolved to pixels. */
|
|
318
|
-
export interface LineChartPoint<TMetric extends string> {
|
|
319
|
-
/** React key. `${metric}:${categoryIndex}`. */
|
|
320
|
-
id: string;
|
|
321
|
-
metric: TMetric;
|
|
322
|
-
categoryIndex: number;
|
|
323
|
-
value: number;
|
|
324
|
-
x: number;
|
|
325
|
-
y: number;
|
|
326
|
-
color: string;
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* One category column: the hit target and everything the tooltip needs.
|
|
330
|
-
*
|
|
331
|
-
* Line charts hit-test by column rather than by proximity to a stroke, so the
|
|
332
|
-
* whole vertical band is a target and the tooltip reports every line at once.
|
|
333
|
-
*/
|
|
334
|
-
export interface LineChartColumn<TMetric extends string> {
|
|
335
|
-
categoryIndex: number;
|
|
336
|
-
label: string;
|
|
337
|
-
/** x of the category tick. */
|
|
338
|
-
x: number;
|
|
339
|
-
/** Full-height hit target, tiling with its neighbours. */
|
|
340
|
-
bandX: number;
|
|
341
|
-
bandWidth: number;
|
|
342
|
-
/** Points present in this column, one per line that has a value here. */
|
|
343
|
-
points: LineChartPoint<TMetric>[];
|
|
344
|
-
/** Topmost point in the column — where the tooltip anchors. */
|
|
345
|
-
anchorY: number;
|
|
346
|
-
}
|
|
347
251
|
/**
|
|
348
252
|
* One slice of a pie or donut.
|
|
349
253
|
*
|
|
@@ -361,44 +265,12 @@ export interface PieChartSliceDatum<TSlice extends string> {
|
|
|
361
265
|
*/
|
|
362
266
|
value: number;
|
|
363
267
|
}
|
|
364
|
-
/** React key used for the bucket that absorbs slices below the fold threshold. */
|
|
365
|
-
export declare const AGGREGATED_SLICE_KEY = "__other__";
|
|
366
|
-
/** One rendered arc. */
|
|
367
|
-
export interface PieChartArc<TSlice extends string> {
|
|
368
|
-
/** React key. The slice key, or {@link AGGREGATED_SLICE_KEY}. */
|
|
369
|
-
id: string;
|
|
370
|
-
/**
|
|
371
|
-
* The originating slice, or `null` for the aggregated bucket.
|
|
372
|
-
*
|
|
373
|
-
* Nullable rather than widened to `string` so callers must acknowledge the
|
|
374
|
-
* synthetic arc instead of accidentally treating it as a real slice key.
|
|
375
|
-
*/
|
|
376
|
-
sliceKey: TSlice | null;
|
|
377
|
-
label: string;
|
|
378
|
-
/** Summed value for the aggregated bucket, the slice's own otherwise. */
|
|
379
|
-
value: number;
|
|
380
|
-
/** Share of the total, 0–1. */
|
|
381
|
-
share: number;
|
|
382
|
-
/** `d` for the arc. */
|
|
383
|
-
path: string;
|
|
384
|
-
/** Radians, clockwise from 12 o'clock. */
|
|
385
|
-
startAngle: number;
|
|
386
|
-
endAngle: number;
|
|
387
|
-
/** Anchor for the tooltip, just outside the arc's outer edge. */
|
|
388
|
-
anchorX: number;
|
|
389
|
-
anchorY: number;
|
|
390
|
-
color: string;
|
|
391
|
-
/** True for the bucket produced by folding small slices together. */
|
|
392
|
-
isAggregated: boolean;
|
|
393
|
-
}
|
|
394
268
|
/** One label/value row in the tooltip. */
|
|
395
269
|
export interface ChartTooltipRow {
|
|
396
270
|
/** React key, unique within the tooltip. */
|
|
397
271
|
key: string;
|
|
398
272
|
/** Row label — a component label, line label or slice label. */
|
|
399
273
|
label: string;
|
|
400
|
-
/** Optional grouping label, used when bars are split by a pivot. */
|
|
401
|
-
group?: string;
|
|
402
274
|
value: number;
|
|
403
275
|
/** Already run through the resolved formatter. */
|
|
404
276
|
formattedValue: string;
|
|
@@ -434,6 +306,33 @@ export interface ChartPlotTooltipModel {
|
|
|
434
306
|
}
|
|
435
307
|
/** Render prop for replacing the tooltip body. Positioning stays with the chart. */
|
|
436
308
|
export type ChartTooltipRenderer = (model: ChartTooltipModel) => ReactNode;
|
|
309
|
+
/** Which shape a category's hit target is drawn as. */
|
|
310
|
+
export declare enum ChartTargetShape {
|
|
311
|
+
/** Cartesian charts: a full-height band over the category. */
|
|
312
|
+
RECT = "RECT",
|
|
313
|
+
/** Radial charts: the arc's own outline, redrawn transparent. */
|
|
314
|
+
PATH = "PATH"
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* One category's interactive target, in plot coordinates.
|
|
318
|
+
*
|
|
319
|
+
* Array position *is* the category index — already true of every geometry
|
|
320
|
+
* builder's output — so there is no index field that could fall out of step.
|
|
321
|
+
* `key` is carried separately because a pie's arcs reorder, where bar and line
|
|
322
|
+
* indices do not.
|
|
323
|
+
*/
|
|
324
|
+
export type ChartCategoryTarget = {
|
|
325
|
+
key: string;
|
|
326
|
+
shape: ChartTargetShape.RECT;
|
|
327
|
+
x: number;
|
|
328
|
+
y: number;
|
|
329
|
+
width: number;
|
|
330
|
+
height: number;
|
|
331
|
+
} | {
|
|
332
|
+
key: string;
|
|
333
|
+
shape: ChartTargetShape.PATH;
|
|
334
|
+
d: string;
|
|
335
|
+
};
|
|
437
336
|
/** One legend entry. */
|
|
438
337
|
export interface ChartLegendItem {
|
|
439
338
|
key: string;
|
|
@@ -500,7 +399,7 @@ export interface ChartFluidBothAxes {
|
|
|
500
399
|
*/
|
|
501
400
|
export type ChartSize = ChartFixedSize | ChartFluidFixedHeight | ChartFluidRatioHeight | ChartFixedWidthFluidHeight | ChartFluidBothAxes;
|
|
502
401
|
/**
|
|
503
|
-
* Props common to every
|
|
402
|
+
* Props common to every chart.
|
|
504
403
|
*
|
|
505
404
|
* Data props are declared per chart, since their shapes and generics differ.
|
|
506
405
|
*/
|
|
@@ -511,7 +410,14 @@ export interface BaseChartProps {
|
|
|
511
410
|
valueUnit?: ChartValueUnit;
|
|
512
411
|
/** Full control over value rendering. Wins over `valueUnit`. */
|
|
513
412
|
valueFormatter?: ChartValueFormatter;
|
|
514
|
-
/**
|
|
413
|
+
/**
|
|
414
|
+
* Format category labels, wherever a category is named.
|
|
415
|
+
*
|
|
416
|
+
* That is the axis and the tooltip heading on the cartesian charts, and
|
|
417
|
+
* additionally the legend on a pie — whose legend lists *slices*, which are
|
|
418
|
+
* its categories. Bar and line legends name series, which come from the
|
|
419
|
+
* `series` record and are not categories, so this does not reach them.
|
|
420
|
+
*/
|
|
515
421
|
labelFormatter?: ChartLabelFormatter;
|
|
516
422
|
/** Replace the tooltip body. Collision handling stays with the chart. */
|
|
517
423
|
tooltipRenderer?: ChartTooltipRenderer;
|
package/dist/charts/types.js
CHANGED
|
@@ -67,6 +67,19 @@ var ChartValueUnit = /* @__PURE__ */ function(ChartValueUnit) {
|
|
|
67
67
|
ChartValueUnit["COMPACT"] = "COMPACT";
|
|
68
68
|
return ChartValueUnit;
|
|
69
69
|
}({});
|
|
70
|
+
/**
|
|
71
|
+
* Which chart is being rendered.
|
|
72
|
+
*
|
|
73
|
+
* Exists so the frame can phrase a default accessible name — a pie has slices
|
|
74
|
+
* where the cartesian charts have categories. Deliberately not a styling hook:
|
|
75
|
+
* nothing else branches on it.
|
|
76
|
+
*/
|
|
77
|
+
var ChartKind = /* @__PURE__ */ function(ChartKind) {
|
|
78
|
+
ChartKind["BAR"] = "BAR";
|
|
79
|
+
ChartKind["LINE"] = "LINE";
|
|
80
|
+
ChartKind["PIE"] = "PIE";
|
|
81
|
+
return ChartKind;
|
|
82
|
+
}({});
|
|
70
83
|
/** How the category axis copes when labels outgrow their slots. */
|
|
71
84
|
var ChartCategoryLabelMode = /* @__PURE__ */ function(ChartCategoryLabelMode) {
|
|
72
85
|
/** Render every label that fits; otherwise show every nth. The default. */
|
|
@@ -130,7 +143,13 @@ var LineChartCurve = /* @__PURE__ */ function(LineChartCurve) {
|
|
|
130
143
|
LineChartCurve["STEP"] = "STEP";
|
|
131
144
|
return LineChartCurve;
|
|
132
145
|
}({});
|
|
133
|
-
/**
|
|
134
|
-
var
|
|
146
|
+
/** Which shape a category's hit target is drawn as. */
|
|
147
|
+
var ChartTargetShape = /* @__PURE__ */ function(ChartTargetShape) {
|
|
148
|
+
/** Cartesian charts: a full-height band over the category. */
|
|
149
|
+
ChartTargetShape["RECT"] = "RECT";
|
|
150
|
+
/** Radial charts: the arc's own outline, redrawn transparent. */
|
|
151
|
+
ChartTargetShape["PATH"] = "PATH";
|
|
152
|
+
return ChartTargetShape;
|
|
153
|
+
}({});
|
|
135
154
|
//#endregion
|
|
136
|
-
export {
|
|
155
|
+
export { BarChartNormalization, BarCorners, ChartCategoryLabelMode, ChartKind, ChartMarkState, ChartPalette, ChartTargetShape, ChartValueUnit, LineChartCurve };
|