@galaxy-io/dls 1.3.4 → 1.3.6
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/accordion/Accordion.d.ts +1 -2
- package/dist/accordion/Accordion.js +18 -26
- package/dist/charts/BarChart.d.ts +1 -7
- package/dist/charts/BarChart.js +42 -20
- package/dist/charts/ChartAxis.d.ts +11 -2
- package/dist/charts/ChartAxis.js +5 -4
- package/dist/charts/ChartCategoryTargets.d.ts +16 -16
- package/dist/charts/ChartCategoryTargets.js +19 -70
- package/dist/charts/ChartFrame.d.ts +14 -12
- package/dist/charts/ChartFrame.js +36 -46
- package/dist/charts/ChartLegend.d.ts +12 -5
- package/dist/charts/ChartLegend.js +31 -6
- package/dist/charts/ChartPrimitives.d.ts +31 -31
- package/dist/charts/ChartPrimitives.js +97 -79
- package/dist/charts/ChartTooltip.js +9 -4
- package/dist/charts/LineChart.d.ts +1 -7
- package/dist/charts/LineChart.js +68 -48
- package/dist/charts/PieChart.d.ts +1 -8
- package/dist/charts/PieChart.js +38 -45
- package/dist/charts/chartFormat.d.ts +1 -9
- package/dist/charts/chartFormat.js +1 -13
- package/dist/charts/constants.d.ts +23 -7
- package/dist/charts/constants.js +82 -8
- package/dist/charts/types.d.ts +14 -4
- package/dist/charts/types.js +15 -4
- package/dist/charts/useChartInteraction.d.ts +15 -32
- package/dist/charts/useChartInteraction.js +9 -89
- package/dist/charts/useSeriesColorResolver.d.ts +7 -0
- package/dist/charts/useSeriesColorResolver.js +2 -1
- package/dist/styles.css +25 -26
- package/dist/switcher/Switcher.js +2 -2
- package/package.json +1 -1
|
@@ -14,7 +14,6 @@ export interface AccordionProps {
|
|
|
14
14
|
variant?: AccordionVariant;
|
|
15
15
|
size?: AccordionSize;
|
|
16
16
|
icon?: PhosphorIcon;
|
|
17
|
-
isTrailingIcon?: boolean;
|
|
18
17
|
header: string;
|
|
19
18
|
subheader?: string;
|
|
20
19
|
metric?: React.ReactNode;
|
|
@@ -26,5 +25,5 @@ export interface AccordionProps {
|
|
|
26
25
|
/** Controlled mode: callback when toggle is clicked */
|
|
27
26
|
onToggle?: () => void;
|
|
28
27
|
}
|
|
29
|
-
declare const Accordion: ({ children, variant, size, icon,
|
|
28
|
+
declare const Accordion: ({ children, variant, size, icon, header, subheader, metric, borderRadius, padding, isOpenInitial, isOpen: controlledIsOpen, onToggle: controlledOnToggle, }: PropsWithChildren<AccordionProps>) => React.JSX.Element;
|
|
30
29
|
export default Accordion;
|
|
@@ -65,7 +65,7 @@ var AccordionContentInner = withTheme(/*#__PURE__*/ styled("div")({
|
|
|
65
65
|
class: "a1f5gwwu",
|
|
66
66
|
propsAsIs: false
|
|
67
67
|
}));
|
|
68
|
-
var Accordion = ({ children, variant = "PRIMARY", size = "MEDIUM", icon,
|
|
68
|
+
var Accordion = ({ children, variant = "PRIMARY", size = "MEDIUM", icon, header, subheader, metric, borderRadius, padding = "12px", isOpenInitial = false, isOpen: controlledIsOpen, onToggle: controlledOnToggle }) => {
|
|
69
69
|
const [internalIsOpen, setInternalIsOpen] = useState(isOpenInitial);
|
|
70
70
|
const isControlled = controlledIsOpen !== void 0;
|
|
71
71
|
const isOpen = isControlled ? controlledIsOpen : internalIsOpen;
|
|
@@ -87,31 +87,23 @@ var Accordion = ({ children, variant = "PRIMARY", size = "MEDIUM", icon, isTrail
|
|
|
87
87
|
children: [/* @__PURE__ */ jsxs(FlexWrapper, {
|
|
88
88
|
alignItems: AlignItems.CENTER,
|
|
89
89
|
gap: 8,
|
|
90
|
-
children: [
|
|
91
|
-
icon
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
})]
|
|
108
|
-
}),
|
|
109
|
-
icon && isTrailingIcon && /* @__PURE__ */ jsx(Icon, {
|
|
110
|
-
component: icon,
|
|
111
|
-
variant: isOpen ? IconVariant.PRIMARY : IconVariant.SECONDARY,
|
|
112
|
-
size: 16
|
|
113
|
-
})
|
|
114
|
-
]
|
|
90
|
+
children: [icon && /* @__PURE__ */ jsx(Icon, {
|
|
91
|
+
component: icon,
|
|
92
|
+
variant: isOpen ? IconVariant.PRIMARY : IconVariant.SECONDARY,
|
|
93
|
+
size: 16
|
|
94
|
+
}), /* @__PURE__ */ jsxs(FlexWrapper, {
|
|
95
|
+
direction: FlexDirection.COLUMN,
|
|
96
|
+
gap: 2,
|
|
97
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
98
|
+
variant: isOpen ? TextVariant.PRIMARY : TextVariant.SECONDARY,
|
|
99
|
+
weight: TextWeight.MEDIUM,
|
|
100
|
+
children: header
|
|
101
|
+
}), subheader && /* @__PURE__ */ jsx(Text, {
|
|
102
|
+
size: TextSize.BODY_SM,
|
|
103
|
+
variant: isOpen ? TextVariant.SECONDARY : TextVariant.TERTIARY,
|
|
104
|
+
children: subheader
|
|
105
|
+
})]
|
|
106
|
+
})]
|
|
115
107
|
}), /* @__PURE__ */ jsxs(FlexWrapper, {
|
|
116
108
|
alignItems: AlignItems.CENTER,
|
|
117
109
|
gap: 8,
|
|
@@ -13,12 +13,6 @@ export type BarChartProps<TMetric extends string, TComponentKey extends string =
|
|
|
13
13
|
groups: BarChartGroupDatum<NoInfer<TMetric>, NoInfer<TComponentKey>>[];
|
|
14
14
|
/** @default BarChartNormalization.NONE */
|
|
15
15
|
normalization?: BarChartNormalization;
|
|
16
|
-
/**
|
|
17
|
-
* Notified when a group is pinned or unpinned by a click.
|
|
18
|
-
*
|
|
19
|
-
* The index is a position in `groups`.
|
|
20
|
-
*/
|
|
21
|
-
onPinnedChange?: (groupIndex: number | null) => void;
|
|
22
16
|
};
|
|
23
17
|
/**
|
|
24
18
|
* Bar chart with a three-level data model.
|
|
@@ -27,5 +21,5 @@ export type BarChartProps<TMetric extends string, TComponentKey extends string =
|
|
|
27
21
|
* `bars` in a group render side by side, several `components` in a bar stack,
|
|
28
22
|
* and a chart doing both at once needs no extra configuration.
|
|
29
23
|
*/
|
|
30
|
-
declare const BarChart: <TMetric extends string, TComponentKey extends string = string>({ series, groups, width, height, fillWidth, fillHeight, aspectRatio, margin, normalization, valueUnit, valueFormatter, labelFormatter, valueDomain, categoryLabelMode, categoryAxisTitle, valueAxisTitle, showGrid, showLegend, noTooltip, tooltipRenderer, isLoading, contentWhenEmpty, ariaLabel, ariaDescription,
|
|
24
|
+
declare const BarChart: <TMetric extends string, TComponentKey extends string = string>({ series, groups, width, height, fillWidth, fillHeight, aspectRatio, margin, normalization, valueUnit, valueFormatter, labelFormatter, valueDomain, categoryLabelMode, categoryAxisTitle, valueAxisTitle, showGrid, showLegend, noTooltip, tooltipRenderer, isLoading, contentWhenEmpty, ariaLabel, ariaDescription, }: BarChartProps<TMetric, TComponentKey>) => import("react").JSX.Element;
|
|
31
25
|
export default BarChart;
|
package/dist/charts/BarChart.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { BarChartNormalization, ChartKind, ChartTargetShape } from "./types.js";
|
|
2
|
+
import { SKELETON_BAR_GROUPS } from "./constants.js";
|
|
2
3
|
import { useSeriesColorResolver } from "./useSeriesColorResolver.js";
|
|
3
4
|
import { useChartInteraction } from "./useChartInteraction.js";
|
|
4
5
|
import { useCartesianChartLayout } from "./useCartesianChartLayout.js";
|
|
5
6
|
import { getBarLegendItems } from "./barChartLegend.js";
|
|
6
7
|
import { buildBarChartGeometry, getBarValueDomain, roundedRectPath } from "./barChartGeometry.js";
|
|
7
|
-
import { ChartBarPath } from "./ChartPrimitives.js";
|
|
8
|
+
import { ChartBarPath, ChartSkeletonGroup } from "./ChartPrimitives.js";
|
|
8
9
|
import ChartFrame from "./ChartFrame.js";
|
|
9
10
|
import { ChartCategoryAxis, ChartValueAxis } from "./ChartAxis.js";
|
|
10
11
|
import { useCallback, useMemo, useRef } from "react";
|
|
@@ -17,7 +18,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
17
18
|
* `bars` in a group render side by side, several `components` in a bar stack,
|
|
18
19
|
* and a chart doing both at once needs no extra configuration.
|
|
19
20
|
*/
|
|
20
|
-
var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRatio, margin, normalization = BarChartNormalization.NONE, valueUnit, valueFormatter, labelFormatter, valueDomain, categoryLabelMode, categoryAxisTitle, valueAxisTitle, showGrid = true, showLegend = true, noTooltip = false, tooltipRenderer, isLoading = false, contentWhenEmpty, ariaLabel, ariaDescription
|
|
21
|
+
var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRatio, margin, normalization = BarChartNormalization.NONE, valueUnit, valueFormatter, labelFormatter, valueDomain, categoryLabelMode, categoryAxisTitle, valueAxisTitle, showGrid = true, showLegend = true, noTooltip = false, tooltipRenderer, isLoading = false, contentWhenEmpty, ariaLabel, ariaDescription }) => {
|
|
21
22
|
const containerRef = useRef(null);
|
|
22
23
|
const colors = useSeriesColorResolver(series);
|
|
23
24
|
/**
|
|
@@ -42,9 +43,29 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
42
43
|
valueFormatter,
|
|
43
44
|
valueUnit
|
|
44
45
|
]);
|
|
46
|
+
/**
|
|
47
|
+
* The data actually rendered: the caller's, or the skeleton's while loading.
|
|
48
|
+
*
|
|
49
|
+
* Loading replaces the chart wholesale with ghost bars pushed through the
|
|
50
|
+
* real geometry pipeline, so the skeleton gets the true radii and spacing.
|
|
51
|
+
* The cast is safe because nothing derived from skeleton data ever surfaces:
|
|
52
|
+
* labels are hidden, targets are off, the legend shows stubs, and the
|
|
53
|
+
* accessible name says "loading" instead of counting.
|
|
54
|
+
*/
|
|
55
|
+
const displayGroups = useMemo(() => isLoading ? SKELETON_BAR_GROUPS.map((values, groupIndex) => ({
|
|
56
|
+
label: `skeleton-${groupIndex}`,
|
|
57
|
+
bars: values.map((value, barIndex) => ({
|
|
58
|
+
metric: `skeleton-${barIndex}`,
|
|
59
|
+
components: [{
|
|
60
|
+
key: "skeleton",
|
|
61
|
+
label: "",
|
|
62
|
+
value
|
|
63
|
+
}]
|
|
64
|
+
}))
|
|
65
|
+
})) : groups, [isLoading, groups]);
|
|
45
66
|
const { dimensions, domain, valueTicks, formatValue, formatLabel, formatAxisValue } = useCartesianChartLayout({
|
|
46
67
|
containerRef,
|
|
47
|
-
rawDomain: useMemo(() => getBarValueDomain(
|
|
68
|
+
rawDomain: useMemo(() => getBarValueDomain(displayGroups, normalization), [displayGroups, normalization]),
|
|
48
69
|
valueDomain,
|
|
49
70
|
width,
|
|
50
71
|
height,
|
|
@@ -69,10 +90,10 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
69
90
|
* takes its metric's colour. Applying the metric colour to a stack would
|
|
70
91
|
* paint every segment identically.
|
|
71
92
|
*/
|
|
72
|
-
const isStacked = useMemo(() =>
|
|
73
|
-
const resolveColor = useCallback(({ metric, componentIndex, isStacked: barIsStacked, explicit }) => barIsStacked ? colors.resolveByIndex(componentIndex, explicit) : colors.resolve(metric, explicit), [colors]);
|
|
93
|
+
const isStacked = useMemo(() => displayGroups.some((group) => group.bars.some((bar) => bar.components.length > 1)), [displayGroups]);
|
|
94
|
+
const resolveColor = useCallback(({ metric, componentIndex, isStacked: barIsStacked, explicit }) => isLoading ? colors.placeholder : barIsStacked ? colors.resolveByIndex(componentIndex, explicit) : colors.resolve(metric, explicit), [colors, isLoading]);
|
|
74
95
|
const geometry = useMemo(() => buildBarChartGeometry({
|
|
75
|
-
groups,
|
|
96
|
+
groups: displayGroups,
|
|
76
97
|
plotWidth,
|
|
77
98
|
plotHeight,
|
|
78
99
|
normalization,
|
|
@@ -80,7 +101,7 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
80
101
|
domain,
|
|
81
102
|
resolveColor
|
|
82
103
|
}), [
|
|
83
|
-
|
|
104
|
+
displayGroups,
|
|
84
105
|
plotWidth,
|
|
85
106
|
plotHeight,
|
|
86
107
|
normalization,
|
|
@@ -88,7 +109,7 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
88
109
|
domain,
|
|
89
110
|
resolveColor
|
|
90
111
|
]);
|
|
91
|
-
const isEmpty =
|
|
112
|
+
const isEmpty = displayGroups.length === 0;
|
|
92
113
|
const legendItems = useMemo(() => getBarLegendItems({
|
|
93
114
|
isStacked,
|
|
94
115
|
series,
|
|
@@ -104,9 +125,7 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
104
125
|
const interaction = useChartInteraction({
|
|
105
126
|
categoryCount: geometry.bands.length,
|
|
106
127
|
seriesKeys: legendKeys,
|
|
107
|
-
disabled: noTooltip || isLoading || isEmpty
|
|
108
|
-
isLoading,
|
|
109
|
-
onPinnedChange
|
|
128
|
+
disabled: noTooltip || isLoading || isEmpty
|
|
110
129
|
});
|
|
111
130
|
const buildCategoryTooltip = useCallback((index) => {
|
|
112
131
|
const band = geometry.bands[index];
|
|
@@ -141,6 +160,14 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
141
160
|
width: band.width,
|
|
142
161
|
height: band.height
|
|
143
162
|
})), [geometry.bands]);
|
|
163
|
+
const marks = geometry.rects.map((rect) => /* @__PURE__ */ jsx(ChartBarPath, {
|
|
164
|
+
d: roundedRectPath(rect.x, rect.y, rect.width, rect.height, rect.radius, rect.corners),
|
|
165
|
+
fill: rect.color,
|
|
166
|
+
"data-state": interaction.getMarkState({
|
|
167
|
+
categoryIndex: rect.groupIndex,
|
|
168
|
+
seriesKey: isStacked ? rect.componentKey : rect.metric
|
|
169
|
+
})
|
|
170
|
+
}, rect.id));
|
|
144
171
|
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
145
172
|
containerRef,
|
|
146
173
|
dimensions,
|
|
@@ -159,15 +186,17 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
159
186
|
marginLeft: dimensions.margin.left,
|
|
160
187
|
formatter: formatAxisValue,
|
|
161
188
|
showGrid,
|
|
189
|
+
showLabels: !isLoading,
|
|
162
190
|
title: valueAxisTitle
|
|
163
191
|
}), /* @__PURE__ */ jsx(ChartCategoryAxis, {
|
|
164
|
-
labels:
|
|
192
|
+
labels: displayGroups.map((group) => group.label),
|
|
165
193
|
positions: categoryPositions,
|
|
166
194
|
step: categoryStep,
|
|
167
195
|
plotWidth,
|
|
168
196
|
plotHeight,
|
|
169
197
|
formatter: formatLabel,
|
|
170
198
|
mode: categoryLabelMode,
|
|
199
|
+
showLabels: !isLoading,
|
|
171
200
|
title: categoryAxisTitle
|
|
172
201
|
})] }),
|
|
173
202
|
noTooltip,
|
|
@@ -180,14 +209,7 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
180
209
|
contentWhenEmpty,
|
|
181
210
|
showLegend,
|
|
182
211
|
legendItems,
|
|
183
|
-
children:
|
|
184
|
-
d: roundedRectPath(rect.x, rect.y, rect.width, rect.height, rect.radius, rect.corners),
|
|
185
|
-
fill: rect.color,
|
|
186
|
-
"data-state": interaction.getMarkState({
|
|
187
|
-
categoryIndex: rect.groupIndex,
|
|
188
|
-
seriesKey: isStacked ? rect.componentKey : rect.metric
|
|
189
|
-
})
|
|
190
|
-
}, rect.id))
|
|
212
|
+
children: isLoading ? /* @__PURE__ */ jsx(ChartSkeletonGroup, { children: marks }) : marks
|
|
191
213
|
});
|
|
192
214
|
};
|
|
193
215
|
//#endregion
|
|
@@ -22,6 +22,13 @@ interface ChartValueAxisProps {
|
|
|
22
22
|
plotHeight: number;
|
|
23
23
|
formatter: ChartValueFormatter;
|
|
24
24
|
showGrid?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Render the tick labels and title.
|
|
27
|
+
*
|
|
28
|
+
* Off while the chart is loading: the grid keeps the plot's structure, but
|
|
29
|
+
* numbers derived from placeholder data would read as data.
|
|
30
|
+
*/
|
|
31
|
+
showLabels?: boolean;
|
|
25
32
|
/**
|
|
26
33
|
* Rotated title in the left gutter.
|
|
27
34
|
*
|
|
@@ -30,7 +37,7 @@ interface ChartValueAxisProps {
|
|
|
30
37
|
*/
|
|
31
38
|
title?: string;
|
|
32
39
|
}
|
|
33
|
-
export declare const ChartValueAxis: ({ ticks, scale, plotWidth, plotHeight, marginLeft, formatter, showGrid, title, }: ChartValueAxisProps) => import("react").JSX.Element;
|
|
40
|
+
export declare const ChartValueAxis: ({ ticks, scale, plotWidth, plotHeight, marginLeft, formatter, showGrid, showLabels, title, }: ChartValueAxisProps) => import("react").JSX.Element;
|
|
34
41
|
interface ChartCategoryAxisProps {
|
|
35
42
|
labels: string[];
|
|
36
43
|
/** Left edge of each category's slot, in plot coordinates. */
|
|
@@ -42,6 +49,8 @@ interface ChartCategoryAxisProps {
|
|
|
42
49
|
plotHeight: number;
|
|
43
50
|
formatter: ChartLabelFormatter;
|
|
44
51
|
mode?: ChartCategoryLabelMode;
|
|
52
|
+
/** Render the labels and title. Off while loading — see the value axis. */
|
|
53
|
+
showLabels?: boolean;
|
|
45
54
|
/**
|
|
46
55
|
* Title below the tick labels.
|
|
47
56
|
*
|
|
@@ -49,5 +58,5 @@ interface ChartCategoryAxisProps {
|
|
|
49
58
|
*/
|
|
50
59
|
title?: string;
|
|
51
60
|
}
|
|
52
|
-
export declare const ChartCategoryAxis: ({ labels, positions, step, plotWidth, plotHeight, formatter, mode, title, }: ChartCategoryAxisProps) => import("react").JSX.Element;
|
|
61
|
+
export declare const ChartCategoryAxis: ({ labels, positions, step, plotWidth, plotHeight, formatter, mode, showLabels, title, }: ChartCategoryAxisProps) => import("react").JSX.Element | null;
|
|
53
62
|
export {};
|
package/dist/charts/ChartAxis.js
CHANGED
|
@@ -6,7 +6,7 @@ import { getCategoryLabelStride } from "./chartScales.js";
|
|
|
6
6
|
import { ChartAxisLabelBox, ChartGridLine } from "./ChartPrimitives.js";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/charts/ChartAxis.tsx
|
|
9
|
-
var ChartValueAxis = ({ ticks, scale, plotWidth, plotHeight, marginLeft, formatter, showGrid = true, title }) => {
|
|
9
|
+
var ChartValueAxis = ({ ticks, scale, plotWidth, plotHeight, marginLeft, formatter, showGrid = true, showLabels = true, title }) => {
|
|
10
10
|
const titleBand = title ? 26 : 0;
|
|
11
11
|
const labelWidth = Math.max(0, marginLeft - titleBand - 12);
|
|
12
12
|
return /* @__PURE__ */ jsxs("g", {
|
|
@@ -18,7 +18,7 @@ var ChartValueAxis = ({ ticks, scale, plotWidth, plotHeight, marginLeft, formatt
|
|
|
18
18
|
x2: plotWidth + 12,
|
|
19
19
|
y1: 0,
|
|
20
20
|
y2: 0
|
|
21
|
-
}), labelWidth > 0 && /* @__PURE__ */ jsx(ChartAxisLabelBox, {
|
|
21
|
+
}), showLabels && labelWidth > 0 && /* @__PURE__ */ jsx(ChartAxisLabelBox, {
|
|
22
22
|
x: -marginLeft + titleBand,
|
|
23
23
|
y: -20 / 2,
|
|
24
24
|
width: labelWidth,
|
|
@@ -37,7 +37,7 @@ var ChartValueAxis = ({ ticks, scale, plotWidth, plotHeight, marginLeft, formatt
|
|
|
37
37
|
})
|
|
38
38
|
})
|
|
39
39
|
})]
|
|
40
|
-
}, tick)), title && /* @__PURE__ */ jsx("g", {
|
|
40
|
+
}, tick)), showLabels && title && /* @__PURE__ */ jsx("g", {
|
|
41
41
|
transform: `translate(${-marginLeft + 18 / 2}, ${plotHeight / 2}) rotate(-90)`,
|
|
42
42
|
children: /* @__PURE__ */ jsx(ChartAxisLabelBox, {
|
|
43
43
|
x: -plotHeight / 2,
|
|
@@ -61,7 +61,8 @@ var ChartValueAxis = ({ ticks, scale, plotWidth, plotHeight, marginLeft, formatt
|
|
|
61
61
|
})]
|
|
62
62
|
});
|
|
63
63
|
};
|
|
64
|
-
var ChartCategoryAxis = ({ labels, positions, step, plotWidth, plotHeight, formatter, mode = ChartCategoryLabelMode.AUTO, title }) => {
|
|
64
|
+
var ChartCategoryAxis = ({ labels, positions, step, plotWidth, plotHeight, formatter, mode = ChartCategoryLabelMode.AUTO, showLabels = true, title }) => {
|
|
65
|
+
if (!showLabels) return null;
|
|
65
66
|
const formatted = labels.map(formatter);
|
|
66
67
|
const stride = mode === ChartCategoryLabelMode.AUTO ? getCategoryLabelStride(formatted, step) : 1;
|
|
67
68
|
const labelWidth = step * stride;
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import type { ChartCategoryTarget } from "./types";
|
|
2
2
|
import type { ChartInteraction } from "./useChartInteraction";
|
|
3
3
|
/**
|
|
4
|
-
* The
|
|
4
|
+
* The hover layer: one transparent target per category, above the marks.
|
|
5
5
|
*
|
|
6
|
-
* Shared by all three charts so
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `data-interactive` instead — and none of them was reachable by keyboard at
|
|
10
|
-
* all.
|
|
6
|
+
* Shared by all three charts so hit testing is spelled once. Targets carry no
|
|
7
|
+
* roles and no tab stops — the plot is `role="img"` and its accessible story is
|
|
8
|
+
* the frame's label and description, while pointer users get the tooltip.
|
|
11
9
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* keyboard reader exactly as they do for a pointer — without
|
|
16
|
-
* `useChartInteraction` growing a third state axis to keep in sync.
|
|
10
|
+
* A category with nothing to show gets no target at all: hovering an all-zero
|
|
11
|
+
* bar group or an all-null line column must not open a tooltip with a heading
|
|
12
|
+
* and no rows, so the empty stretch of plot is simply not hoverable.
|
|
17
13
|
*/
|
|
18
14
|
interface ChartCategoryTargetsProps {
|
|
19
15
|
targets: ChartCategoryTarget[];
|
|
20
16
|
interaction: ChartInteraction;
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Category indices whose tooltip would have no rows.
|
|
19
|
+
*
|
|
20
|
+
* Skipped entirely rather than rendered inert, so the pointer falls through
|
|
21
|
+
* to nothing. Indexing is unaffected: `targets.map` still passes the true
|
|
22
|
+
* category index for every target that does render.
|
|
23
|
+
*/
|
|
24
|
+
inertIndices?: ReadonlySet<number>;
|
|
25
25
|
}
|
|
26
|
-
declare const ChartCategoryTargets: ({ targets, interaction,
|
|
26
|
+
declare const ChartCategoryTargets: ({ targets, interaction, inertIndices, }: ChartCategoryTargetsProps) => import("react").JSX.Element;
|
|
27
27
|
export default ChartCategoryTargets;
|
|
@@ -1,75 +1,24 @@
|
|
|
1
1
|
import { ChartTargetShape } from "./types.js";
|
|
2
|
-
import {
|
|
3
|
-
import { ChartCategoryTargetLayer, ChartHitTarget, ChartHitTargetPath } from "./ChartPrimitives.js";
|
|
2
|
+
import { ChartHitTarget, ChartHitTargetPath } from "./ChartPrimitives.js";
|
|
4
3
|
import { match } from "ts-pattern";
|
|
5
|
-
import {
|
|
6
|
-
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
7
5
|
//#region src/charts/ChartCategoryTargets.tsx
|
|
8
|
-
var ChartCategoryTargets = ({ targets, interaction,
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const onKeyDown = useCallback((event, index) => {
|
|
26
|
-
if (match(event.key).with("ArrowRight", "ArrowDown", () => moveTo(index + 1)).with("ArrowLeft", "ArrowUp", () => moveTo(index - 1)).with("Home", () => moveTo(0)).with("End", () => moveTo(targets.length - 1)).with("Enter", " ", () => interaction.onCategoryClick(index)).with("Escape", () => interaction.onBackdropClick()).otherwise(() => void 0) !== void 0 || [
|
|
27
|
-
"ArrowRight",
|
|
28
|
-
"ArrowDown",
|
|
29
|
-
"ArrowLeft",
|
|
30
|
-
"ArrowUp",
|
|
31
|
-
"Home",
|
|
32
|
-
"End",
|
|
33
|
-
"Enter",
|
|
34
|
-
" ",
|
|
35
|
-
"Escape"
|
|
36
|
-
].includes(event.key)) event.preventDefault();
|
|
37
|
-
}, [
|
|
38
|
-
moveTo,
|
|
39
|
-
interaction,
|
|
40
|
-
targets.length
|
|
41
|
-
]);
|
|
42
|
-
return /* @__PURE__ */ jsx(ChartCategoryTargetLayer, { children: targets.map((target, index) => {
|
|
43
|
-
const shared = {
|
|
44
|
-
tabIndex: index === rovingIndex ? 0 : -1,
|
|
45
|
-
role: "button",
|
|
46
|
-
"aria-label": getAriaLabel(index),
|
|
47
|
-
"aria-pressed": interaction.pinnedIndex === index,
|
|
48
|
-
"data-interactive": "true",
|
|
49
|
-
onFocus: () => interaction.onCategoryEnter(index),
|
|
50
|
-
onBlur: () => interaction.onCategoryLeave(),
|
|
51
|
-
onMouseEnter: () => interaction.onCategoryEnter(index),
|
|
52
|
-
onMouseLeave: () => interaction.onCategoryLeave(),
|
|
53
|
-
onClick: () => interaction.onCategoryClick(index),
|
|
54
|
-
onKeyDown: (event) => onKeyDown(event, index)
|
|
55
|
-
};
|
|
56
|
-
return match(target).with({ shape: ChartTargetShape.RECT }, (rect) => /* @__PURE__ */ jsx(ChartHitTarget, {
|
|
57
|
-
ref: (node) => {
|
|
58
|
-
nodeRefs.current[index] = node;
|
|
59
|
-
},
|
|
60
|
-
x: rect.x,
|
|
61
|
-
y: rect.y,
|
|
62
|
-
width: rect.width,
|
|
63
|
-
height: rect.height,
|
|
64
|
-
...shared
|
|
65
|
-
}, rect.key)).with({ shape: ChartTargetShape.PATH }, (path) => /* @__PURE__ */ jsx(ChartHitTargetPath, {
|
|
66
|
-
ref: (node) => {
|
|
67
|
-
nodeRefs.current[index] = node;
|
|
68
|
-
},
|
|
69
|
-
d: path.d,
|
|
70
|
-
...shared
|
|
71
|
-
}, path.key)).exhaustive();
|
|
72
|
-
}) });
|
|
73
|
-
};
|
|
6
|
+
var ChartCategoryTargets = ({ targets, interaction, inertIndices }) => /* @__PURE__ */ jsx(Fragment, { children: targets.map((target, index) => {
|
|
7
|
+
if (inertIndices?.has(index)) return null;
|
|
8
|
+
const shared = {
|
|
9
|
+
onMouseEnter: () => interaction.onCategoryEnter(index),
|
|
10
|
+
onMouseLeave: () => interaction.onCategoryLeave()
|
|
11
|
+
};
|
|
12
|
+
return match(target).with({ shape: ChartTargetShape.RECT }, (rect) => /* @__PURE__ */ jsx(ChartHitTarget, {
|
|
13
|
+
x: rect.x,
|
|
14
|
+
y: rect.y,
|
|
15
|
+
width: rect.width,
|
|
16
|
+
height: rect.height,
|
|
17
|
+
...shared
|
|
18
|
+
}, rect.key)).with({ shape: ChartTargetShape.PATH }, (path) => /* @__PURE__ */ jsx(ChartHitTargetPath, {
|
|
19
|
+
d: path.d,
|
|
20
|
+
...shared
|
|
21
|
+
}, path.key)).exhaustive();
|
|
22
|
+
}) });
|
|
74
23
|
//#endregion
|
|
75
24
|
export { ChartCategoryTargets as default };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
import { ChartKind } from "./types";
|
|
2
|
+
import { ChartKind, ChartLegendPlacement } from "./types";
|
|
3
3
|
import type { ChartCategoryTarget, ChartLegendItem, ChartPlotTooltipModel, ChartTooltipRenderer } from "./types";
|
|
4
4
|
import type { ChartDimensions } from "./useChartDimensions";
|
|
5
5
|
import type { ChartInteraction } from "./useChartInteraction";
|
|
6
6
|
import type { ChartTooltipVerticalAlign } from "./useChartTooltipPosition";
|
|
7
7
|
/**
|
|
8
8
|
* The shell every chart renders into: measured root, reserved plot box, SVG and
|
|
9
|
-
* its margin translate, the
|
|
10
|
-
*
|
|
9
|
+
* its margin translate, the plot group, the hover targets, the tooltip, the
|
|
10
|
+
* empty state and the legend.
|
|
11
11
|
*
|
|
12
12
|
* **The frame owns the plot translate.** Marks are drawn inside a
|
|
13
13
|
* `translate(margin.left, margin.top)` group, and every coordinate handed to
|
|
@@ -56,7 +56,7 @@ export interface ChartFrameProps {
|
|
|
56
56
|
*/
|
|
57
57
|
axes?: ReactNode;
|
|
58
58
|
/**
|
|
59
|
-
* Marks, drawn inside the plot group
|
|
59
|
+
* Marks, drawn inside the plot group beneath the hover targets.
|
|
60
60
|
*
|
|
61
61
|
* Rendered only once measured, so no caller writes that guard. Note it is
|
|
62
62
|
* still *evaluated* on the unmeasured pass — as is the geometry it maps over,
|
|
@@ -72,8 +72,8 @@ export interface ChartFrameProps {
|
|
|
72
72
|
*
|
|
73
73
|
* Taken as a function rather than a finished model because the frame needs it
|
|
74
74
|
* twice: once for the category under the pointer, and once per category to
|
|
75
|
-
*
|
|
76
|
-
* makes
|
|
75
|
+
* decide which categories are inert. Deriving both from the same builder is
|
|
76
|
+
* what makes "no tooltip rows" and "not hoverable" the same fact.
|
|
77
77
|
*
|
|
78
78
|
* Must be stable; memoize it at the call site.
|
|
79
79
|
*/
|
|
@@ -88,10 +88,6 @@ export interface ChartFrameProps {
|
|
|
88
88
|
categoryTargets?: ChartCategoryTarget[];
|
|
89
89
|
/** Applied to the target layer. Radial charts pass their centre translate. */
|
|
90
90
|
categoryTargetsTransform?: string;
|
|
91
|
-
/** Arrow keys wrap at the ends. True for radial charts. */
|
|
92
|
-
wrapCategoryNavigation?: boolean;
|
|
93
|
-
/** Overrides the accessible name of a category, which defaults to its tooltip. */
|
|
94
|
-
describeCategory?: (index: number) => string;
|
|
95
91
|
/** Half a category's width, so the tooltip sits beside the marks. */
|
|
96
92
|
anchorHalfWidth?: number;
|
|
97
93
|
/** Radial charts pass their centre, in plot coordinates. */
|
|
@@ -103,8 +99,14 @@ export interface ChartFrameProps {
|
|
|
103
99
|
contentWhenEmpty?: ReactNode;
|
|
104
100
|
showLegend?: boolean;
|
|
105
101
|
legendItems: ChartLegendItem[];
|
|
106
|
-
/**
|
|
102
|
+
/** Where the legend sits. RIGHT stacks it beside the plot, vertically centred. */
|
|
103
|
+
legendPlacement?: ChartLegendPlacement;
|
|
104
|
+
/**
|
|
105
|
+
* BOTTOM: left padding, defaulting to the left margin so the legend aligns
|
|
106
|
+
* with the plot rather than the axis gutter. RIGHT: the gap between the plot
|
|
107
|
+
* box and the legend, defaulting to {@link CHART_LEGEND_SIDE_GAP}.
|
|
108
|
+
*/
|
|
107
109
|
legendInset?: number;
|
|
108
110
|
}
|
|
109
|
-
declare const ChartFrame: ({ containerRef, dimensions, fillWidth, fillHeight, interaction, kind, categoryCount, ariaLabel, ariaDescription, axes, children, plotOverlay, noTooltip, buildCategoryTooltip, tooltipRenderer, categoryTargets, categoryTargetsTransform,
|
|
111
|
+
declare const ChartFrame: ({ containerRef, dimensions, fillWidth, fillHeight, interaction, kind, categoryCount, ariaLabel, ariaDescription, axes, children, plotOverlay, noTooltip, buildCategoryTooltip, tooltipRenderer, categoryTargets, categoryTargetsTransform, anchorHalfWidth, placeAwayFromX, verticalAlign, isEmpty, isLoading, contentWhenEmpty, showLegend, legendItems, legendPlacement, legendInset, }: ChartFrameProps) => import("react").JSX.Element;
|
|
110
112
|
export default ChartFrame;
|