@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
|
@@ -123,6 +123,30 @@ var ChartArcPath = /*#__PURE__*/ styled("path")({
|
|
|
123
123
|
propsAsIs: true
|
|
124
124
|
});
|
|
125
125
|
/**
|
|
126
|
+
* Wrapper for the category target layer.
|
|
127
|
+
*
|
|
128
|
+
* Exists to carry the focus-ring colour: the targets themselves are plain
|
|
129
|
+
* `styled.x` because they receive refs (see the module note above), so they
|
|
130
|
+
* cannot read the theme directly. Setting `color` here lets them use
|
|
131
|
+
* `currentColor` and still take the token rather than inheriting whatever the
|
|
132
|
+
* consumer's page happens to set.
|
|
133
|
+
*/
|
|
134
|
+
var _exp11 = () => ({ theme }) => theme.color.border.selected;
|
|
135
|
+
var ChartCategoryTargetLayer = withTheme(/*#__PURE__*/ styled("g")({
|
|
136
|
+
name: "ChartCategoryTargetLayer",
|
|
137
|
+
class: "c1wvzvu4",
|
|
138
|
+
propsAsIs: true,
|
|
139
|
+
vars: { "c1wvzvu4-0": [_exp11()] }
|
|
140
|
+
}));
|
|
141
|
+
/**
|
|
142
|
+
* Shared by both target shapes.
|
|
143
|
+
*
|
|
144
|
+
* The ring is a `stroke`, not an `outline`: `outline` on SVG elements is a late
|
|
145
|
+
* arrival in WebKit and `outline-offset` behaves inconsistently across engines,
|
|
146
|
+
* while a stroke on a transparent shape is universally supported — and it
|
|
147
|
+
* traces a pie arc, which a rectangular outline could not.
|
|
148
|
+
*/
|
|
149
|
+
/**
|
|
126
150
|
* Per-category hit target, rendered above the marks.
|
|
127
151
|
*
|
|
128
152
|
* Hit testing the full column rather than the bars themselves means a two-pixel
|
|
@@ -132,13 +156,26 @@ var ChartArcPath = /*#__PURE__*/ styled("path")({
|
|
|
132
156
|
*/
|
|
133
157
|
var ChartHitTarget = /*#__PURE__*/ styled("rect")({
|
|
134
158
|
name: "ChartHitTarget",
|
|
135
|
-
class: "
|
|
159
|
+
class: "c17guewt",
|
|
160
|
+
propsAsIs: true
|
|
161
|
+
});
|
|
162
|
+
/**
|
|
163
|
+
* The radial equivalent, reusing the arc's own `d`.
|
|
164
|
+
*
|
|
165
|
+
* A pie has no category axis to band, so its targets are the arc shapes
|
|
166
|
+
* themselves — drawn again, transparent, above the marks. That keeps hit
|
|
167
|
+
* testing and focus identical across all three charts instead of the pie
|
|
168
|
+
* hit-testing its visible arcs directly.
|
|
169
|
+
*/
|
|
170
|
+
var ChartHitTargetPath = /*#__PURE__*/ styled("path")({
|
|
171
|
+
name: "ChartHitTargetPath",
|
|
172
|
+
class: "cblgiyf",
|
|
136
173
|
propsAsIs: true
|
|
137
174
|
});
|
|
138
175
|
/** Full-plot backdrop; clicking it clears a pinned category. */
|
|
139
176
|
var ChartBackdrop = /*#__PURE__*/ styled("rect")({
|
|
140
177
|
name: "ChartBackdrop",
|
|
141
|
-
class: "
|
|
178
|
+
class: "c1lr03cc",
|
|
142
179
|
propsAsIs: true
|
|
143
180
|
});
|
|
144
181
|
/**
|
|
@@ -146,24 +183,24 @@ var ChartBackdrop = /*#__PURE__*/ styled("rect")({
|
|
|
146
183
|
* zero — the line under the bars is what makes them read as resting on a
|
|
147
184
|
* baseline.
|
|
148
185
|
*/
|
|
149
|
-
var
|
|
186
|
+
var _exp14 = () => ({ theme }) => theme.color.border.primary;
|
|
150
187
|
var ChartGridLine = withTheme(/*#__PURE__*/ styled("line")({
|
|
151
188
|
name: "ChartGridLine",
|
|
152
|
-
class: "
|
|
189
|
+
class: "cizy1s8",
|
|
153
190
|
propsAsIs: true,
|
|
154
|
-
vars: { "
|
|
191
|
+
vars: { "cizy1s8-0": [_exp14()] }
|
|
155
192
|
}));
|
|
156
193
|
/** Vertical rule marking the hovered category on a line chart. */
|
|
157
|
-
var
|
|
194
|
+
var _exp15 = () => ({ theme }) => theme.color.border.secondary;
|
|
158
195
|
var ChartCursorLine = withTheme(/*#__PURE__*/ styled("line")({
|
|
159
196
|
name: "ChartCursorLine",
|
|
160
|
-
class: "
|
|
197
|
+
class: "c1ukq11d",
|
|
161
198
|
propsAsIs: true,
|
|
162
|
-
vars: { "
|
|
199
|
+
vars: { "c1ukq11d-0": [_exp15()] }
|
|
163
200
|
}));
|
|
164
201
|
var ChartAxisLabelBox = /*#__PURE__*/ styled("foreignObject")({
|
|
165
202
|
name: "ChartAxisLabelBox",
|
|
166
|
-
class: "
|
|
203
|
+
class: "cwcko2m",
|
|
167
204
|
propsAsIs: true
|
|
168
205
|
});
|
|
169
206
|
/**
|
|
@@ -173,21 +210,21 @@ var ChartAxisLabelBox = /*#__PURE__*/ styled("foreignObject")({
|
|
|
173
210
|
* than teleporting, and it stays mounted while hidden so the fade can actually
|
|
174
211
|
* run — unmounting on hide is why a fade-out never appears.
|
|
175
212
|
*/
|
|
176
|
-
var
|
|
177
|
-
var
|
|
178
|
-
var
|
|
179
|
-
var
|
|
180
|
-
var
|
|
213
|
+
var _exp16 = () => ({ $x }) => `${$x}px`;
|
|
214
|
+
var _exp17 = () => ({ $y }) => `${$y}px`;
|
|
215
|
+
var _exp20 = () => ({ theme }) => theme.color.border.primary;
|
|
216
|
+
var _exp21 = () => ({ theme }) => theme.color.background.primary;
|
|
217
|
+
var _exp22 = () => ({ $isVisible }) => $isVisible ? 1 : 0;
|
|
181
218
|
var ChartTooltipPositioner = withTheme(/*#__PURE__*/ styled("div")({
|
|
182
219
|
name: "ChartTooltipPositioner",
|
|
183
|
-
class: "
|
|
220
|
+
class: "cqwhvyz",
|
|
184
221
|
propsAsIs: false,
|
|
185
222
|
vars: {
|
|
186
|
-
"
|
|
187
|
-
"
|
|
188
|
-
"
|
|
189
|
-
"
|
|
190
|
-
"
|
|
223
|
+
"cqwhvyz-0": [_exp16()],
|
|
224
|
+
"cqwhvyz-1": [_exp17()],
|
|
225
|
+
"cqwhvyz-2": [_exp20()],
|
|
226
|
+
"cqwhvyz-3": [_exp21()],
|
|
227
|
+
"cqwhvyz-4": [_exp22()]
|
|
191
228
|
}
|
|
192
229
|
}));
|
|
193
230
|
/**
|
|
@@ -198,32 +235,32 @@ var ChartTooltipPositioner = withTheme(/*#__PURE__*/ styled("div")({
|
|
|
198
235
|
* of the DLS. `pointer-events: none` keeps it from stealing hover from the arc
|
|
199
236
|
* behind it.
|
|
200
237
|
*/
|
|
201
|
-
var
|
|
202
|
-
var
|
|
203
|
-
var
|
|
238
|
+
var _exp26 = () => ({ $centerX }) => `${$centerX}px`;
|
|
239
|
+
var _exp27 = () => ({ $centerY }) => `${$centerY}px`;
|
|
240
|
+
var _exp29 = () => ({ $diameter }) => `${$diameter}px`;
|
|
204
241
|
var ChartCenterBox = /*#__PURE__*/ styled("div")({
|
|
205
242
|
name: "ChartCenterBox",
|
|
206
|
-
class: "
|
|
243
|
+
class: "c1iaray",
|
|
207
244
|
propsAsIs: false,
|
|
208
245
|
vars: {
|
|
209
|
-
"
|
|
210
|
-
"
|
|
211
|
-
"
|
|
246
|
+
"c1iaray-0": [_exp26()],
|
|
247
|
+
"c1iaray-1": [_exp27()],
|
|
248
|
+
"c1iaray-2": [_exp29()]
|
|
212
249
|
}
|
|
213
250
|
});
|
|
214
251
|
/**
|
|
215
252
|
* Sits slightly above centre, over where the bars would be, so the axes stay
|
|
216
253
|
* legible underneath.
|
|
217
254
|
*/
|
|
218
|
-
var
|
|
219
|
-
var
|
|
255
|
+
var _exp30 = () => ({ theme }) => theme.color.border.primary;
|
|
256
|
+
var _exp31 = () => ({ theme }) => theme.color.background.tertiary;
|
|
220
257
|
var ChartEmptyOverlay = withTheme(/*#__PURE__*/ styled("div")({
|
|
221
258
|
name: "ChartEmptyOverlay",
|
|
222
|
-
class: "
|
|
259
|
+
class: "cz6jod1",
|
|
223
260
|
propsAsIs: false,
|
|
224
261
|
vars: {
|
|
225
|
-
"
|
|
226
|
-
"
|
|
262
|
+
"cz6jod1-0": [_exp30()],
|
|
263
|
+
"cz6jod1-1": [_exp31()]
|
|
227
264
|
}
|
|
228
265
|
}));
|
|
229
266
|
/**
|
|
@@ -235,12 +272,12 @@ var ChartEmptyOverlay = withTheme(/*#__PURE__*/ styled("div")({
|
|
|
235
272
|
* the marks dim instantly while their legend entries sit through the full
|
|
236
273
|
* {@link CHART_RESTORE_DELAY_MS}, and the two visibly fall out of step.
|
|
237
274
|
*/
|
|
238
|
-
var
|
|
275
|
+
var _exp32 = () => ({ $inset }) => `${$inset}px`;
|
|
239
276
|
var ChartLegendRow = /*#__PURE__*/ styled("div")({
|
|
240
277
|
name: "ChartLegendRow",
|
|
241
|
-
class: "
|
|
278
|
+
class: "c1de5mqk",
|
|
242
279
|
propsAsIs: false,
|
|
243
|
-
vars: { "
|
|
280
|
+
vars: { "c1de5mqk-0": [_exp32()] }
|
|
244
281
|
});
|
|
245
282
|
/**
|
|
246
283
|
* One legend entry, when the legend is interactive.
|
|
@@ -255,14 +292,14 @@ var ChartLegendRow = /*#__PURE__*/ styled("div")({
|
|
|
255
292
|
*/
|
|
256
293
|
var ChartLegendItemButton = /*#__PURE__*/ styled("button")({
|
|
257
294
|
name: "ChartLegendItemButton",
|
|
258
|
-
class: "
|
|
295
|
+
class: "cjirv6a",
|
|
259
296
|
propsAsIs: false
|
|
260
297
|
});
|
|
261
298
|
/** The same row, when the legend is inert — no button semantics to announce. */
|
|
262
299
|
var ChartLegendItemStatic = /*#__PURE__*/ styled("div")({
|
|
263
300
|
name: "ChartLegendItemStatic",
|
|
264
|
-
class: "
|
|
301
|
+
class: "c1armna5",
|
|
265
302
|
propsAsIs: false
|
|
266
303
|
});
|
|
267
304
|
//#endregion
|
|
268
|
-
export { ChartArcPath, ChartAreaPath, ChartAxisLabelBox, ChartBackdrop, ChartBarPath, ChartCenterBox, ChartCursorLine, ChartEmptyOverlay, ChartGridLine, ChartHitTarget, ChartLegendItemButton, ChartLegendItemStatic, ChartLegendRow, ChartLinePath, ChartPlotBox, ChartPlotGroup, ChartPointCircle, ChartRoot, ChartSvg, ChartTooltipPositioner };
|
|
305
|
+
export { ChartArcPath, ChartAreaPath, ChartAxisLabelBox, ChartBackdrop, ChartBarPath, ChartCategoryTargetLayer, ChartCenterBox, ChartCursorLine, ChartEmptyOverlay, ChartGridLine, ChartHitTarget, ChartHitTargetPath, ChartLegendItemButton, ChartLegendItemStatic, ChartLegendRow, ChartLinePath, ChartPlotBox, ChartPlotGroup, ChartPointCircle, ChartRoot, ChartSvg, ChartTooltipPositioner };
|
|
@@ -7,7 +7,7 @@ import { ChartTooltipVerticalAlign } from "./useChartTooltipPosition";
|
|
|
7
7
|
* still gets collision handling — in V1 the custom path received no positioning
|
|
8
8
|
* at all and had to reimplement it.
|
|
9
9
|
*/
|
|
10
|
-
interface
|
|
10
|
+
interface ChartTooltipProps {
|
|
11
11
|
/**
|
|
12
12
|
* The model to display, or `null` when nothing is active.
|
|
13
13
|
*
|
|
@@ -24,5 +24,5 @@ interface ChartHoverTooltipProps {
|
|
|
24
24
|
verticalAlign?: ChartTooltipVerticalAlign;
|
|
25
25
|
renderer?: ChartTooltipRenderer;
|
|
26
26
|
}
|
|
27
|
-
declare const
|
|
28
|
-
export default
|
|
27
|
+
declare const ChartTooltip: ({ model, containerWidth, containerHeight, anchorHalfWidth, placeAwayFromX, verticalAlign, renderer, }: ChartTooltipProps) => import("react").JSX.Element;
|
|
28
|
+
export default ChartTooltip;
|
|
@@ -7,7 +7,7 @@ import { ChartTooltipPositioner } from "./ChartPrimitives.js";
|
|
|
7
7
|
import { useState } from "react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/charts/ChartTooltip.tsx
|
|
10
|
-
var
|
|
10
|
+
var ChartTooltip = ({ model, containerWidth, containerHeight, anchorHalfWidth, placeAwayFromX, verticalAlign, renderer }) => {
|
|
11
11
|
const [retained, setRetained] = useState(model);
|
|
12
12
|
if (model !== null && model !== retained) setRetained(model);
|
|
13
13
|
const { tooltipRef, x, y, isMeasured } = useChartTooltipPosition({
|
|
@@ -69,4 +69,4 @@ var ChartHoverTooltip = ({ model, containerWidth, containerHeight, anchorHalfWid
|
|
|
69
69
|
});
|
|
70
70
|
};
|
|
71
71
|
//#endregion
|
|
72
|
-
export {
|
|
72
|
+
export { ChartTooltip as default };
|
package/dist/charts/LineChart.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ChartMarkState, LineChartCurve } from "./types.js";
|
|
1
|
+
import { ChartKind, ChartTargetShape, LineChartCurve } from "./types.js";
|
|
3
2
|
import { LINE_AREA_OPACITY, LINE_POINT_RADIUS } from "./constants.js";
|
|
4
|
-
import {
|
|
3
|
+
import { useSeriesColorResolver } from "./useSeriesColorResolver.js";
|
|
5
4
|
import { useChartInteraction } from "./useChartInteraction.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { resolveSeriesColor } from "./chartTheme.js";
|
|
10
|
-
import { ChartAreaPath, ChartCursorLine, ChartHitTarget, ChartLinePath, ChartPointCircle } from "./ChartPrimitives.js";
|
|
5
|
+
import { useCartesianChartLayout } from "./useCartesianChartLayout.js";
|
|
6
|
+
import { buildLineChartGeometry, getLineValueDomain } from "./lineChartGeometry.js";
|
|
7
|
+
import { ChartAreaPath, ChartCursorLine, ChartLinePath, ChartPointCircle } from "./ChartPrimitives.js";
|
|
11
8
|
import ChartFrame from "./ChartFrame.js";
|
|
12
9
|
import { ChartCategoryAxis, ChartValueAxis } from "./ChartAxis.js";
|
|
13
10
|
import { useCallback, useMemo, useRef } from "react";
|
|
@@ -22,39 +19,33 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
22
19
|
* nearest-point-to-cursor model needs.
|
|
23
20
|
*/
|
|
24
21
|
var LineChart = ({ series, lines, categories, width, height, fillWidth, fillHeight, aspectRatio, margin, curve = LineChartCurve.SMOOTH, strokeWidth, showCursor = true, valueUnit, valueFormatter, labelFormatter, valueDomain, categoryLabelMode, categoryAxisTitle, valueAxisTitle, showGrid = true, showLegend = true, noTooltip = false, tooltipRenderer, isLoading = false, contentWhenEmpty, ariaLabel, ariaDescription, onPinnedChange }) => {
|
|
25
|
-
const { theme } = useGalaxyTheme();
|
|
26
22
|
const containerRef = useRef(null);
|
|
27
|
-
const
|
|
23
|
+
const colors = useSeriesColorResolver(series);
|
|
24
|
+
const { dimensions, domain, valueTicks, formatValue, formatLabel } = useCartesianChartLayout({
|
|
28
25
|
containerRef,
|
|
26
|
+
rawDomain: useMemo(() => getLineValueDomain(lines), [lines]),
|
|
27
|
+
valueDomain,
|
|
29
28
|
width,
|
|
30
29
|
height,
|
|
31
30
|
fillWidth,
|
|
32
31
|
fillHeight,
|
|
33
32
|
aspectRatio,
|
|
34
|
-
margin
|
|
35
|
-
hasValueTitle: Boolean(valueAxisTitle),
|
|
36
|
-
hasCategoryTitle: Boolean(categoryAxisTitle)
|
|
37
|
-
})
|
|
38
|
-
});
|
|
39
|
-
const { plotWidth, plotHeight } = dimensions;
|
|
40
|
-
const { formatValue, formatLabel } = useChartFormatters({
|
|
41
|
-
valueFormatter,
|
|
33
|
+
margin,
|
|
42
34
|
valueUnit,
|
|
43
|
-
|
|
35
|
+
valueFormatter,
|
|
36
|
+
labelFormatter,
|
|
37
|
+
valueAxisTitle,
|
|
38
|
+
categoryAxisTitle
|
|
44
39
|
});
|
|
45
|
-
const
|
|
46
|
-
const resolveColor = useCallback(({ metric }) =>
|
|
47
|
-
theme,
|
|
48
|
-
metricKeys,
|
|
49
|
-
series
|
|
50
|
-
]);
|
|
40
|
+
const { plotWidth, plotHeight } = dimensions;
|
|
41
|
+
const resolveColor = useCallback(({ metric }) => colors.resolve(metric), [colors]);
|
|
51
42
|
const geometry = useMemo(() => buildLineChartGeometry({
|
|
52
43
|
lines,
|
|
53
44
|
categories,
|
|
54
45
|
plotWidth,
|
|
55
46
|
plotHeight,
|
|
56
47
|
curve,
|
|
57
|
-
|
|
48
|
+
domain,
|
|
58
49
|
strokeWidth,
|
|
59
50
|
resolveColor
|
|
60
51
|
}), [
|
|
@@ -63,35 +54,29 @@ var LineChart = ({ series, lines, categories, width, height, fillWidth, fillHeig
|
|
|
63
54
|
plotWidth,
|
|
64
55
|
plotHeight,
|
|
65
56
|
curve,
|
|
66
|
-
|
|
57
|
+
domain,
|
|
67
58
|
strokeWidth,
|
|
68
59
|
resolveColor
|
|
69
60
|
]);
|
|
70
|
-
const valueTicks = useMemo(() => getValueTicks(geometry.valueScale, valueDomain), [geometry.valueScale, valueDomain]);
|
|
71
61
|
const isEmpty = geometry.categories.length === 0 || lines.length === 0;
|
|
72
|
-
const legendItems = useMemo(() =>
|
|
62
|
+
const legendItems = useMemo(() => colors.keys.map((metric) => ({
|
|
73
63
|
key: metric,
|
|
74
64
|
label: series[metric].label,
|
|
75
|
-
color:
|
|
76
|
-
|
|
77
|
-
lineIndex
|
|
78
|
-
})
|
|
79
|
-
})), [
|
|
80
|
-
metricKeys,
|
|
81
|
-
series,
|
|
82
|
-
resolveColor
|
|
83
|
-
]);
|
|
65
|
+
color: colors.resolve(metric)
|
|
66
|
+
})), [colors, series]);
|
|
84
67
|
const legendKeys = useMemo(() => legendItems.map((item) => item.key), [legendItems]);
|
|
85
68
|
const interaction = useChartInteraction({
|
|
86
69
|
categoryCount: geometry.columns.length,
|
|
87
70
|
seriesKeys: legendKeys,
|
|
88
71
|
disabled: noTooltip || isLoading || isEmpty,
|
|
72
|
+
isLoading,
|
|
89
73
|
onPinnedChange
|
|
90
74
|
});
|
|
91
75
|
const activeColumn = interaction.activeIndex === null ? null : geometry.columns[interaction.activeIndex];
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
76
|
+
const buildCategoryTooltip = useCallback((index) => {
|
|
77
|
+
const column = geometry.columns[index];
|
|
78
|
+
if (!column) return null;
|
|
79
|
+
const rows = [...column.points].sort((a, b) => b.value - a.value).map((point) => ({
|
|
95
80
|
key: point.id,
|
|
96
81
|
label: series[point.metric]?.label ?? point.metric,
|
|
97
82
|
value: point.value,
|
|
@@ -99,26 +84,35 @@ var LineChart = ({ series, lines, categories, width, height, fillWidth, fillHeig
|
|
|
99
84
|
color: point.color
|
|
100
85
|
}));
|
|
101
86
|
return {
|
|
102
|
-
label: formatLabel(
|
|
87
|
+
label: formatLabel(column.label),
|
|
103
88
|
rows,
|
|
104
|
-
anchorX:
|
|
105
|
-
anchorY:
|
|
89
|
+
anchorX: column.x,
|
|
90
|
+
anchorY: column.anchorY
|
|
106
91
|
};
|
|
107
92
|
}, [
|
|
108
|
-
|
|
109
|
-
activeColumn,
|
|
93
|
+
geometry.columns,
|
|
110
94
|
series,
|
|
111
95
|
formatValue,
|
|
112
96
|
formatLabel
|
|
113
97
|
]);
|
|
114
98
|
const categoryPositions = useMemo(() => geometry.columns.map((column) => column.x - geometry.step / 2), [geometry.columns, geometry.step]);
|
|
99
|
+
const categoryTargets = useMemo(() => geometry.columns.map((column) => ({
|
|
100
|
+
key: String(column.categoryIndex),
|
|
101
|
+
shape: ChartTargetShape.RECT,
|
|
102
|
+
x: column.bandX,
|
|
103
|
+
y: 0,
|
|
104
|
+
width: column.bandWidth,
|
|
105
|
+
height: plotHeight
|
|
106
|
+
})), [geometry.columns, plotHeight]);
|
|
115
107
|
return /* @__PURE__ */ jsxs(ChartFrame, {
|
|
116
108
|
containerRef,
|
|
117
109
|
dimensions,
|
|
118
110
|
fillWidth,
|
|
119
111
|
fillHeight,
|
|
120
112
|
interaction,
|
|
121
|
-
|
|
113
|
+
kind: ChartKind.LINE,
|
|
114
|
+
categoryCount: geometry.categories.length,
|
|
115
|
+
ariaLabel,
|
|
122
116
|
ariaDescription,
|
|
123
117
|
axes: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ChartValueAxis, {
|
|
124
118
|
ticks: valueTicks,
|
|
@@ -140,8 +134,9 @@ var LineChart = ({ series, lines, categories, width, height, fillWidth, fillHeig
|
|
|
140
134
|
title: categoryAxisTitle
|
|
141
135
|
})] }),
|
|
142
136
|
noTooltip,
|
|
143
|
-
|
|
137
|
+
buildCategoryTooltip,
|
|
144
138
|
tooltipRenderer,
|
|
139
|
+
categoryTargets,
|
|
145
140
|
anchorHalfWidth: geometry.step / 2,
|
|
146
141
|
isEmpty,
|
|
147
142
|
isLoading,
|
|
@@ -153,7 +148,7 @@ var LineChart = ({ series, lines, categories, width, height, fillWidth, fillHeig
|
|
|
153
148
|
d: linePath.areaPath,
|
|
154
149
|
fill: linePath.color,
|
|
155
150
|
fillOpacity: LINE_AREA_OPACITY,
|
|
156
|
-
"data-state":
|
|
151
|
+
"data-state": interaction.getMarkState({ seriesKey: linePath.metric })
|
|
157
152
|
}, `${linePath.id}:area`) : null),
|
|
158
153
|
showCursor && activeColumn && /* @__PURE__ */ jsx(ChartCursorLine, {
|
|
159
154
|
x1: activeColumn.x,
|
|
@@ -166,14 +161,14 @@ var LineChart = ({ series, lines, categories, width, height, fillWidth, fillHeig
|
|
|
166
161
|
stroke: linePath.color,
|
|
167
162
|
strokeWidth: linePath.strokeWidth,
|
|
168
163
|
strokeDasharray: linePath.dashArray,
|
|
169
|
-
"data-state":
|
|
164
|
+
"data-state": interaction.getMarkState({ seriesKey: linePath.metric })
|
|
170
165
|
}, linePath.id)),
|
|
171
166
|
geometry.isolatedPoints.map((point) => /* @__PURE__ */ jsx(ChartPointCircle, {
|
|
172
167
|
cx: point.x,
|
|
173
168
|
cy: point.y,
|
|
174
169
|
r: LINE_POINT_RADIUS,
|
|
175
170
|
fill: point.color,
|
|
176
|
-
"data-state":
|
|
171
|
+
"data-state": interaction.getMarkState({ seriesKey: point.metric })
|
|
177
172
|
}, `${point.id}:isolated`)),
|
|
178
173
|
activeColumn?.points.map((point) => /* @__PURE__ */ jsx(ChartPointCircle, {
|
|
179
174
|
cx: point.x,
|
|
@@ -181,17 +176,7 @@ var LineChart = ({ series, lines, categories, width, height, fillWidth, fillHeig
|
|
|
181
176
|
r: LINE_POINT_RADIUS,
|
|
182
177
|
fill: point.color,
|
|
183
178
|
"data-state": interaction.getMarkState({ seriesKey: point.metric })
|
|
184
|
-
}, point.id))
|
|
185
|
-
!noTooltip && !isLoading && geometry.columns.map((column) => /* @__PURE__ */ jsx(ChartHitTarget, {
|
|
186
|
-
x: column.bandX,
|
|
187
|
-
y: 0,
|
|
188
|
-
width: column.bandWidth,
|
|
189
|
-
height: plotHeight,
|
|
190
|
-
"data-interactive": "true",
|
|
191
|
-
onMouseEnter: () => interaction.onCategoryEnter(column.categoryIndex),
|
|
192
|
-
onMouseLeave: interaction.onCategoryLeave,
|
|
193
|
-
onClick: () => interaction.onCategoryClick(column.categoryIndex)
|
|
194
|
-
}, column.categoryIndex))
|
|
179
|
+
}, point.id))
|
|
195
180
|
]
|
|
196
181
|
});
|
|
197
182
|
};
|
package/dist/charts/PieChart.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { useGalaxyTheme } from "../theme/GalaxyTheme.js";
|
|
2
1
|
import FlexWrapper, { AlignItems, FlexDirection, JustifyContent } from "../containers/FlexWrapper.js";
|
|
3
|
-
import {
|
|
2
|
+
import { ChartKind, ChartTargetShape } from "./types.js";
|
|
4
3
|
import { PIE_CHART_MARGIN, PIE_MIN_SLICE_SHARE } from "./constants.js";
|
|
4
|
+
import { useSeriesColorResolver } from "./useSeriesColorResolver.js";
|
|
5
5
|
import { ChartTooltipVerticalAlign } from "./useChartTooltipPosition.js";
|
|
6
6
|
import { useChartInteraction } from "./useChartInteraction.js";
|
|
7
7
|
import { useChartFormatters } from "./useChartFormatters.js";
|
|
8
8
|
import { useChartDimensions } from "./useChartDimensions.js";
|
|
9
9
|
import { buildPieChartGeometry } from "./pieChartGeometry.js";
|
|
10
|
-
import { resolveChartPaletteColor, resolveSeriesColor } from "./chartTheme.js";
|
|
11
10
|
import { ChartArcPath, ChartCenterBox } from "./ChartPrimitives.js";
|
|
12
11
|
import ChartFrame from "./ChartFrame.js";
|
|
13
12
|
import { useCallback, useMemo, useRef } from "react";
|
|
@@ -21,8 +20,8 @@ import { jsx } from "react/jsx-runtime";
|
|
|
21
20
|
* default, which keeps every remaining arc large enough to actually hit.
|
|
22
21
|
*/
|
|
23
22
|
var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRatio, margin, innerRadiusRatio, padAngle, cornerRadius, minSliceShare = PIE_MIN_SLICE_SHARE, aggregatedLabel, centerContent, valueUnit, valueFormatter, labelFormatter, showLegend = true, noTooltip = false, tooltipRenderer, isLoading = false, contentWhenEmpty, ariaLabel, ariaDescription, onPinnedChange }) => {
|
|
24
|
-
const { theme } = useGalaxyTheme();
|
|
25
23
|
const containerRef = useRef(null);
|
|
24
|
+
const colors = useSeriesColorResolver(series);
|
|
26
25
|
const dimensions = useChartDimensions({
|
|
27
26
|
containerRef,
|
|
28
27
|
width,
|
|
@@ -30,7 +29,8 @@ var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRa
|
|
|
30
29
|
fillWidth,
|
|
31
30
|
fillHeight,
|
|
32
31
|
aspectRatio,
|
|
33
|
-
margin
|
|
32
|
+
margin,
|
|
33
|
+
defaultMargin: PIE_CHART_MARGIN
|
|
34
34
|
});
|
|
35
35
|
const { plotWidth, plotHeight } = dimensions;
|
|
36
36
|
const { formatValue, formatLabel } = useChartFormatters({
|
|
@@ -38,15 +38,9 @@ var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRa
|
|
|
38
38
|
valueUnit,
|
|
39
39
|
labelFormatter
|
|
40
40
|
});
|
|
41
|
-
const sliceKeys = useMemo(() => Object.keys(series), [series]);
|
|
42
41
|
const getSliceLabel = useCallback((sliceKey) => series[sliceKey]?.label ?? sliceKey, [series]);
|
|
43
42
|
const getSliceColor = useCallback((sliceKey) => series[sliceKey]?.color, [series]);
|
|
44
|
-
const resolveColor = useCallback(({ sliceKey,
|
|
45
|
-
if (explicit) return resolveChartPaletteColor(theme, explicit);
|
|
46
|
-
if (sliceKey === null) return theme.color.text.tertiary;
|
|
47
|
-
const slotIndex = sliceKeys.indexOf(sliceKey);
|
|
48
|
-
return resolveSeriesColor(theme, slotIndex >= 0 ? slotIndex : index);
|
|
49
|
-
}, [theme, sliceKeys]);
|
|
43
|
+
const resolveColor = useCallback(({ sliceKey, explicit }) => sliceKey === null ? colors.neutral : colors.resolve(sliceKey, explicit), [colors]);
|
|
50
44
|
const geometry = useMemo(() => buildPieChartGeometry({
|
|
51
45
|
slices,
|
|
52
46
|
plotWidth,
|
|
@@ -83,11 +77,11 @@ var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRa
|
|
|
83
77
|
categoryCount: geometry.arcs.length,
|
|
84
78
|
seriesKeys: legendKeys,
|
|
85
79
|
disabled: noTooltip || isLoading || isEmpty,
|
|
80
|
+
isLoading,
|
|
86
81
|
onPinnedChange
|
|
87
82
|
});
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
const chartArc = geometry.arcs[interaction.activeIndex];
|
|
83
|
+
const buildCategoryTooltip = useCallback((index) => {
|
|
84
|
+
const chartArc = geometry.arcs[index];
|
|
91
85
|
if (!chartArc) return null;
|
|
92
86
|
return {
|
|
93
87
|
label: formatLabel(chartArc.label),
|
|
@@ -102,12 +96,39 @@ var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRa
|
|
|
102
96
|
anchorY: chartArc.anchorY
|
|
103
97
|
};
|
|
104
98
|
}, [
|
|
105
|
-
noTooltip,
|
|
106
|
-
interaction.activeIndex,
|
|
107
99
|
geometry.arcs,
|
|
108
100
|
formatValue,
|
|
109
101
|
formatLabel
|
|
110
102
|
]);
|
|
103
|
+
/**
|
|
104
|
+
* A slice reads better than the generic "label: row, row" sentence.
|
|
105
|
+
*
|
|
106
|
+
* The frame's default would render "Enterprise: 42.1% of total 1,240", which
|
|
107
|
+
* puts the share where a reader expects the value.
|
|
108
|
+
*/
|
|
109
|
+
const describeCategory = useCallback((index) => {
|
|
110
|
+
const chartArc = geometry.arcs[index];
|
|
111
|
+
if (!chartArc) return "";
|
|
112
|
+
const share = `${Math.round(chartArc.share * 1e3) / 10}% of total`;
|
|
113
|
+
return `${formatLabel(chartArc.label)}, ${formatValue(chartArc.value)}, ${share}`;
|
|
114
|
+
}, [
|
|
115
|
+
geometry.arcs,
|
|
116
|
+
formatValue,
|
|
117
|
+
formatLabel
|
|
118
|
+
]);
|
|
119
|
+
/**
|
|
120
|
+
* Targets reuse each arc's own `d`, drawn again transparent above the marks.
|
|
121
|
+
*
|
|
122
|
+
* The arcs themselves stop being interactive: hit testing, focus and the
|
|
123
|
+
* focus ring then work identically on all three charts, instead of the pie
|
|
124
|
+
* attaching handlers permanently and toggling `data-interactive` while the
|
|
125
|
+
* cartesian charts rendered their targets away.
|
|
126
|
+
*/
|
|
127
|
+
const categoryTargets = useMemo(() => geometry.arcs.map((chartArc) => ({
|
|
128
|
+
key: chartArc.id,
|
|
129
|
+
shape: ChartTargetShape.PATH,
|
|
130
|
+
d: chartArc.path
|
|
131
|
+
})), [geometry.arcs]);
|
|
111
132
|
const showCenter = centerContent && (innerRadiusRatio ?? .62) > 0;
|
|
112
133
|
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
113
134
|
containerRef,
|
|
@@ -115,11 +136,17 @@ var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRa
|
|
|
115
136
|
fillWidth,
|
|
116
137
|
fillHeight,
|
|
117
138
|
interaction,
|
|
118
|
-
|
|
139
|
+
kind: ChartKind.PIE,
|
|
140
|
+
categoryCount: geometry.arcs.length,
|
|
141
|
+
ariaLabel,
|
|
119
142
|
ariaDescription,
|
|
120
143
|
noTooltip,
|
|
121
|
-
|
|
144
|
+
buildCategoryTooltip,
|
|
122
145
|
tooltipRenderer,
|
|
146
|
+
categoryTargets,
|
|
147
|
+
categoryTargetsTransform: `translate(${geometry.centerX}, ${geometry.centerY})`,
|
|
148
|
+
wrapCategoryNavigation: true,
|
|
149
|
+
describeCategory,
|
|
123
150
|
placeAwayFromX: geometry.centerX,
|
|
124
151
|
verticalAlign: ChartTooltipVerticalAlign.CENTERED,
|
|
125
152
|
isEmpty,
|
|
@@ -139,15 +166,10 @@ var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRa
|
|
|
139
166
|
children: geometry.arcs.map((chartArc, index) => /* @__PURE__ */ jsx(ChartArcPath, {
|
|
140
167
|
d: chartArc.path,
|
|
141
168
|
fill: chartArc.color,
|
|
142
|
-
"data-state":
|
|
169
|
+
"data-state": interaction.getMarkState({
|
|
143
170
|
categoryIndex: index,
|
|
144
171
|
seriesKey: chartArc.id
|
|
145
|
-
})
|
|
146
|
-
"data-interactive": noTooltip || isLoading ? "false" : "true",
|
|
147
|
-
onMouseEnter: () => interaction.onCategoryEnter(index),
|
|
148
|
-
onMouseLeave: interaction.onCategoryLeave,
|
|
149
|
-
onClick: () => interaction.onCategoryClick(index),
|
|
150
|
-
"aria-label": `${chartArc.label}: ${formatValue(chartArc.value)}`
|
|
172
|
+
})
|
|
151
173
|
}, chartArc.id))
|
|
152
174
|
})
|
|
153
175
|
});
|