@galaxy-io/dls 1.3.4 → 1.3.5
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 +2 -3
- 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 +33 -45
- package/dist/charts/ChartLegend.d.ts +4 -5
- package/dist/charts/ChartLegend.js +5 -6
- package/dist/charts/ChartPrimitives.d.ts +21 -34
- package/dist/charts/ChartPrimitives.js +86 -85
- package/dist/charts/LineChart.d.ts +1 -7
- package/dist/charts/LineChart.js +2 -3
- package/dist/charts/PieChart.d.ts +1 -8
- package/dist/charts/PieChart.js +6 -27
- package/dist/charts/chartFormat.d.ts +1 -9
- package/dist/charts/chartFormat.js +1 -13
- package/dist/charts/constants.d.ts +4 -7
- package/dist/charts/constants.js +5 -8
- package/dist/charts/types.d.ts +14 -4
- package/dist/charts/types.js +15 -4
- package/dist/charts/useChartInteraction.d.ts +15 -22
- package/dist/charts/useChartInteraction.js +8 -83
- package/dist/styles.css +18 -20
- 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
|
@@ -17,7 +17,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
17
17
|
* `bars` in a group render side by side, several `components` in a bar stack,
|
|
18
18
|
* and a chart doing both at once needs no extra configuration.
|
|
19
19
|
*/
|
|
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
|
|
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
21
|
const containerRef = useRef(null);
|
|
22
22
|
const colors = useSeriesColorResolver(series);
|
|
23
23
|
/**
|
|
@@ -105,8 +105,7 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
|
|
|
105
105
|
categoryCount: geometry.bands.length,
|
|
106
106
|
seriesKeys: legendKeys,
|
|
107
107
|
disabled: noTooltip || isLoading || isEmpty,
|
|
108
|
-
isLoading
|
|
109
|
-
onPinnedChange
|
|
108
|
+
isLoading
|
|
110
109
|
});
|
|
111
110
|
const buildCategoryTooltip = useCallback((index) => {
|
|
112
111
|
const band = geometry.bands[index];
|
|
@@ -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;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { ChartKind } from "./types.js";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
1
|
+
import { ChartKind, ChartLegendPlacement } from "./types.js";
|
|
2
|
+
import "./constants.js";
|
|
3
|
+
import { ChartPlotBox, ChartPlotGroup, ChartRoot, ChartSvg } from "./ChartPrimitives.js";
|
|
4
4
|
import ChartCategoryTargets from "./ChartCategoryTargets.js";
|
|
5
5
|
import ChartEmptyState from "./ChartEmptyState.js";
|
|
6
6
|
import ChartLegend from "./ChartLegend.js";
|
|
7
7
|
import ChartTooltip from "./ChartTooltip.js";
|
|
8
8
|
import { match } from "ts-pattern";
|
|
9
|
-
import {
|
|
9
|
+
import { useId, useMemo } from "react";
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
//#region src/charts/ChartFrame.tsx
|
|
12
|
-
var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction, kind, categoryCount, ariaLabel, ariaDescription, axes, children, plotOverlay, noTooltip = false, buildCategoryTooltip, tooltipRenderer, categoryTargets, categoryTargetsTransform,
|
|
13
|
-
const { width, height,
|
|
12
|
+
var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction, kind, categoryCount, ariaLabel, ariaDescription, axes, children, plotOverlay, noTooltip = false, buildCategoryTooltip, tooltipRenderer, categoryTargets, categoryTargetsTransform, anchorHalfWidth, placeAwayFromX, verticalAlign, isEmpty, isLoading = false, contentWhenEmpty, showLegend = false, legendItems, legendPlacement = ChartLegendPlacement.BOTTOM, legendInset }) => {
|
|
13
|
+
const { width, height, margin, isMeasured, reservedHeight, reservedAspectRatio } = dimensions;
|
|
14
14
|
const generatedId = useId();
|
|
15
15
|
const descriptionId = ariaDescription ? `${generatedId}-desc` : void 0;
|
|
16
16
|
/**
|
|
@@ -48,41 +48,39 @@ var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction
|
|
|
48
48
|
margin.top
|
|
49
49
|
]);
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
51
|
+
* Categories whose tooltip would have no rows.
|
|
52
52
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
53
|
+
* Decided here — from the same builder that feeds the visible tooltip — so
|
|
54
|
+
* "no data at this X" means exactly one thing in every chart: an all-zero
|
|
55
|
+
* bar group and an all-null line column both produce a rowless model, and
|
|
56
|
+
* neither should be hoverable. Their targets are simply not rendered.
|
|
55
57
|
*/
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
* nothing inside it can ever be focused *and* announced. A chart with live
|
|
67
|
-
* targets therefore has to be a `group` — and everything that is not a target
|
|
68
|
-
* has to be explicitly hidden, since under `group` it would otherwise become
|
|
69
|
-
* traversable. When there is nothing to reach, `img` stays: it announces one
|
|
70
|
-
* summary rather than an empty group.
|
|
71
|
-
*/
|
|
72
|
-
const hasFocusableTargets = isMeasured && !noTooltip && !isLoading && !isEmpty && (categoryTargets?.length ?? 0) > 0;
|
|
58
|
+
const inertIndices = useMemo(() => {
|
|
59
|
+
const inert = /* @__PURE__ */ new Set();
|
|
60
|
+
(categoryTargets ?? []).forEach((_, index) => {
|
|
61
|
+
const model = buildCategoryTooltip(index);
|
|
62
|
+
if (!model || model.rows.length === 0) inert.add(index);
|
|
63
|
+
});
|
|
64
|
+
return inert;
|
|
65
|
+
}, [categoryTargets, buildCategoryTooltip]);
|
|
66
|
+
const hasTargets = isMeasured && !noTooltip && !isLoading && !isEmpty && (categoryTargets?.length ?? 0) > 0;
|
|
67
|
+
const legendRight = legendPlacement === ChartLegendPlacement.RIGHT;
|
|
73
68
|
return /* @__PURE__ */ jsxs(ChartRoot, {
|
|
74
69
|
$fillWidth: fillWidth,
|
|
75
70
|
$fillHeight: fillHeight,
|
|
71
|
+
$legendRight: legendRight,
|
|
76
72
|
children: [/* @__PURE__ */ jsxs(ChartPlotBox, {
|
|
77
73
|
ref: containerRef,
|
|
78
74
|
$reservedHeight: reservedHeight,
|
|
79
75
|
$reservedAspectRatio: reservedAspectRatio,
|
|
80
76
|
$fillHeight: fillHeight,
|
|
77
|
+
$legendRight: legendRight,
|
|
78
|
+
$squareFromHeight: legendRight && fillWidth && reservedAspectRatio === void 0,
|
|
81
79
|
children: [
|
|
82
80
|
isMeasured && /* @__PURE__ */ jsxs(ChartSvg, {
|
|
83
81
|
width,
|
|
84
82
|
height,
|
|
85
|
-
role:
|
|
83
|
+
role: "img",
|
|
86
84
|
"aria-label": resolvedAriaLabel,
|
|
87
85
|
"aria-describedby": descriptionId,
|
|
88
86
|
children: [ariaDescription && /* @__PURE__ */ jsx("desc", {
|
|
@@ -92,25 +90,16 @@ var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction
|
|
|
92
90
|
transform: `translate(${margin.left}, ${margin.top})`,
|
|
93
91
|
children: [
|
|
94
92
|
axes,
|
|
95
|
-
/* @__PURE__ */ jsx(
|
|
96
|
-
"
|
|
97
|
-
children
|
|
98
|
-
"data-active": interaction.isEngaged ? "true" : "false",
|
|
99
|
-
children: [/* @__PURE__ */ jsx(ChartBackdrop, {
|
|
100
|
-
width: plotWidth,
|
|
101
|
-
height: plotHeight,
|
|
102
|
-
"data-interactive": interaction.pinnedIndex !== null ? "true" : "false",
|
|
103
|
-
onClick: interaction.onBackdropClick
|
|
104
|
-
}), children]
|
|
105
|
-
})
|
|
93
|
+
/* @__PURE__ */ jsx(ChartPlotGroup, {
|
|
94
|
+
"data-active": interaction.isEngaged ? "true" : "false",
|
|
95
|
+
children
|
|
106
96
|
}),
|
|
107
|
-
|
|
97
|
+
hasTargets && categoryTargets && /* @__PURE__ */ jsx("g", {
|
|
108
98
|
transform: categoryTargetsTransform,
|
|
109
99
|
children: /* @__PURE__ */ jsx(ChartCategoryTargets, {
|
|
110
100
|
targets: categoryTargets,
|
|
111
101
|
interaction,
|
|
112
|
-
|
|
113
|
-
wrap: wrapCategoryNavigation
|
|
102
|
+
inertIndices
|
|
114
103
|
})
|
|
115
104
|
})
|
|
116
105
|
]
|
|
@@ -130,12 +119,11 @@ var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction
|
|
|
130
119
|
]
|
|
131
120
|
}), showLegend && /* @__PURE__ */ jsx(ChartLegend, {
|
|
132
121
|
items: legendItems,
|
|
133
|
-
inset: legendInset ?? margin.left,
|
|
122
|
+
inset: legendInset ?? (legendRight ? 16 : margin.left),
|
|
123
|
+
vertical: legendRight,
|
|
134
124
|
hoveredKey: interaction.hoveredSeriesKey,
|
|
135
|
-
pinnedKey: interaction.pinnedSeriesKey,
|
|
136
125
|
onItemEnter: interaction.onSeriesEnter,
|
|
137
|
-
onItemLeave: interaction.onSeriesLeave
|
|
138
|
-
onItemClick: interaction.onSeriesClick
|
|
126
|
+
onItemLeave: interaction.onSeriesLeave
|
|
139
127
|
})]
|
|
140
128
|
});
|
|
141
129
|
};
|
|
@@ -5,20 +5,19 @@ interface ChartLegendProps {
|
|
|
5
5
|
inset: number;
|
|
6
6
|
/** Series key currently hovered anywhere in the chart. */
|
|
7
7
|
hoveredKey?: string | null;
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/** Stack entries in a column — the side-placed layout. */
|
|
9
|
+
vertical?: boolean;
|
|
10
10
|
/**
|
|
11
11
|
* Supplying these makes the legend interactive. Omit them and it renders as
|
|
12
12
|
* inert text, with no button semantics for a screen reader to announce.
|
|
13
13
|
*/
|
|
14
14
|
onItemEnter?: (key: string) => void;
|
|
15
15
|
onItemLeave?: () => void;
|
|
16
|
-
onItemClick?: (key: string) => void;
|
|
17
16
|
}
|
|
18
17
|
/**
|
|
19
18
|
* Legend for the chart components.
|
|
20
19
|
*
|
|
21
|
-
* Hovering an entry isolates its series
|
|
20
|
+
* Hovering or focusing an entry isolates its series; leaving releases it.
|
|
22
21
|
*
|
|
23
22
|
* Deliberately *not* a visibility toggle: hiding a series would have to rescale
|
|
24
23
|
* the value axis to stay honest — otherwise the remaining bars sit mysteriously
|
|
@@ -26,5 +25,5 @@ interface ChartLegendProps {
|
|
|
26
25
|
* Isolation only changes opacity, so the domain is untouched and the numbers
|
|
27
26
|
* keep meaning what they did.
|
|
28
27
|
*/
|
|
29
|
-
declare const ChartLegend: ({ items, inset, hoveredKey,
|
|
28
|
+
declare const ChartLegend: ({ items, inset, hoveredKey, vertical, onItemEnter, onItemLeave, }: ChartLegendProps) => import("react").JSX.Element | null;
|
|
30
29
|
export default ChartLegend;
|
|
@@ -7,7 +7,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
/**
|
|
8
8
|
* Legend for the chart components.
|
|
9
9
|
*
|
|
10
|
-
* Hovering an entry isolates its series
|
|
10
|
+
* Hovering or focusing an entry isolates its series; leaving releases it.
|
|
11
11
|
*
|
|
12
12
|
* Deliberately *not* a visibility toggle: hiding a series would have to rescale
|
|
13
13
|
* the value axis to stay honest — otherwise the remaining bars sit mysteriously
|
|
@@ -15,12 +15,13 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
* Isolation only changes opacity, so the domain is untouched and the numbers
|
|
16
16
|
* keep meaning what they did.
|
|
17
17
|
*/
|
|
18
|
-
var ChartLegend = ({ items, inset, hoveredKey = null,
|
|
18
|
+
var ChartLegend = ({ items, inset, hoveredKey = null, vertical = false, onItemEnter, onItemLeave }) => {
|
|
19
19
|
if (items.length === 0) return null;
|
|
20
|
-
const isInteractive = Boolean(onItemEnter
|
|
21
|
-
const activeKey =
|
|
20
|
+
const isInteractive = Boolean(onItemEnter);
|
|
21
|
+
const activeKey = hoveredKey;
|
|
22
22
|
return /* @__PURE__ */ jsx(ChartLegendRow, {
|
|
23
23
|
$inset: inset,
|
|
24
|
+
$vertical: vertical,
|
|
24
25
|
"data-active": activeKey !== null ? "true" : "false",
|
|
25
26
|
children: items.map((item) => {
|
|
26
27
|
const state = activeKey === null || item.key === activeKey ? ChartMarkState.ACTIVE : ChartMarkState.MUTED;
|
|
@@ -38,12 +39,10 @@ var ChartLegend = ({ items, inset, hoveredKey = null, pinnedKey = null, onItemEn
|
|
|
38
39
|
return /* @__PURE__ */ jsx(ChartLegendItemButton, {
|
|
39
40
|
type: "button",
|
|
40
41
|
"data-state": state,
|
|
41
|
-
"aria-pressed": pinnedKey === item.key,
|
|
42
42
|
onMouseEnter: () => onItemEnter?.(item.key),
|
|
43
43
|
onMouseLeave: () => onItemLeave?.(),
|
|
44
44
|
onFocus: () => onItemEnter?.(item.key),
|
|
45
45
|
onBlur: () => onItemLeave?.(),
|
|
46
|
-
onClick: () => onItemClick?.(item.key),
|
|
47
46
|
children: content
|
|
48
47
|
}, item.key);
|
|
49
48
|
})
|
|
@@ -4,10 +4,18 @@
|
|
|
4
4
|
* `min-width: 0` is load-bearing rather than cosmetic — without it a chart in a
|
|
5
5
|
* flex row feeds its min-content width back into the ResizeObserver and the
|
|
6
6
|
* measurement can oscillate.
|
|
7
|
+
*
|
|
8
|
+
* `$legendRight` rotates the layout: plot box and legend become a row with
|
|
9
|
+
* `align-items: center`, which is the whole of "the legend is vertically
|
|
10
|
+
* centred on the pie" — the pie is inscribed centred in its box, so centring
|
|
11
|
+
* the legend against the box centres it against the pie. It also holds in the
|
|
12
|
+
* other direction: a legend taller than the box centres the *pie* against the
|
|
13
|
+
* legend instead of pinning it to the top.
|
|
7
14
|
*/
|
|
8
15
|
export declare const ChartRoot: import("@linaria/react").StyledComponent<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & {
|
|
9
16
|
$fillWidth?: boolean;
|
|
10
17
|
$fillHeight?: boolean;
|
|
18
|
+
$legendRight?: boolean;
|
|
11
19
|
}>;
|
|
12
20
|
/**
|
|
13
21
|
* Holds the plot, anchors the tooltip, and is the element that gets measured.
|
|
@@ -29,6 +37,8 @@ export declare const ChartPlotBox: import("@linaria/react").StyledComponent<impo
|
|
|
29
37
|
$reservedHeight?: number;
|
|
30
38
|
$reservedAspectRatio?: number;
|
|
31
39
|
$fillHeight?: boolean;
|
|
40
|
+
$legendRight?: boolean;
|
|
41
|
+
$squareFromHeight?: boolean;
|
|
32
42
|
}>;
|
|
33
43
|
/**
|
|
34
44
|
* `overflow: visible` lets a value label above a full-height bar paint outside
|
|
@@ -45,32 +55,6 @@ export declare const ChartLinePath: import("@linaria/react").StyledComponent<imp
|
|
|
45
55
|
export declare const ChartAreaPath: import("@linaria/react").StyledComponent<import("react").SVGProps<SVGPathElement> & Record<never, unknown>>;
|
|
46
56
|
export declare const ChartPointCircle: import("@linaria/react").StyledComponent<import("react").SVGProps<SVGCircleElement> & Record<never, unknown>>;
|
|
47
57
|
export declare const ChartArcPath: import("@linaria/react").StyledComponent<import("react").SVGProps<SVGPathElement> & Record<never, unknown>>;
|
|
48
|
-
/**
|
|
49
|
-
* Wrapper for the category target layer.
|
|
50
|
-
*
|
|
51
|
-
* Exists to carry the focus-ring colour: the targets themselves are plain
|
|
52
|
-
* `styled.x` because they receive refs (see the module note above), so they
|
|
53
|
-
* cannot read the theme directly. Setting `color` here lets them use
|
|
54
|
-
* `currentColor` and still take the token rather than inheriting whatever the
|
|
55
|
-
* consumer's page happens to set.
|
|
56
|
-
*/
|
|
57
|
-
export declare const ChartCategoryTargetLayer: import("react").ComponentType<Pick<import("react").SVGProps<SVGGElement> & {
|
|
58
|
-
theme: import("../theme").Theme;
|
|
59
|
-
} & {
|
|
60
|
-
as?: React.ElementType;
|
|
61
|
-
}, "as" | keyof import("react").SVGProps<SVGGElement>> & {
|
|
62
|
-
theme?: import("@callstack/react-theme-provider").$DeepPartial<import("../theme").Theme> | undefined;
|
|
63
|
-
}> & import("@callstack/react-theme-provider/typings/hoist-non-react-statics").NonReactStatics<import("react").ComponentType<import("react").SVGProps<SVGGElement> & {
|
|
64
|
-
theme: import("../theme").Theme;
|
|
65
|
-
} & {
|
|
66
|
-
as?: React.ElementType;
|
|
67
|
-
}> & {
|
|
68
|
-
__wyw_meta: unknown;
|
|
69
|
-
} & import("react").FunctionComponent<import("react").SVGProps<SVGGElement> & {
|
|
70
|
-
theme: import("../theme").Theme;
|
|
71
|
-
} & {
|
|
72
|
-
as?: React.ElementType;
|
|
73
|
-
}>, {}>;
|
|
74
58
|
/**
|
|
75
59
|
* Per-category hit target, rendered above the marks.
|
|
76
60
|
*
|
|
@@ -78,6 +62,9 @@ export declare const ChartCategoryTargetLayer: import("react").ComponentType<Pic
|
|
|
78
62
|
* bar is as easy to hover as a two-hundred-pixel one, and crossing between
|
|
79
63
|
* segments inside a category fires no events at all — so the tooltip holds
|
|
80
64
|
* still instead of chasing each segment.
|
|
65
|
+
*
|
|
66
|
+
* No cursor and no focus treatment: the target only previews on hover, and a
|
|
67
|
+
* pointer cursor would promise a click that does nothing.
|
|
81
68
|
*/
|
|
82
69
|
export declare const ChartHitTarget: import("@linaria/react").StyledComponent<import("react").SVGProps<SVGRectElement> & Record<never, unknown>>;
|
|
83
70
|
/**
|
|
@@ -85,12 +72,10 @@ export declare const ChartHitTarget: import("@linaria/react").StyledComponent<im
|
|
|
85
72
|
*
|
|
86
73
|
* A pie has no category axis to band, so its targets are the arc shapes
|
|
87
74
|
* themselves — drawn again, transparent, above the marks. That keeps hit
|
|
88
|
-
* testing
|
|
89
|
-
*
|
|
75
|
+
* testing identical across all three charts instead of the pie hit-testing its
|
|
76
|
+
* visible arcs directly.
|
|
90
77
|
*/
|
|
91
78
|
export declare const ChartHitTargetPath: import("@linaria/react").StyledComponent<import("react").SVGProps<SVGPathElement> & Record<never, unknown>>;
|
|
92
|
-
/** Full-plot backdrop; clicking it clears a pinned category. */
|
|
93
|
-
export declare const ChartBackdrop: import("@linaria/react").StyledComponent<import("react").SVGProps<SVGRectElement> & Record<never, unknown>>;
|
|
94
79
|
/**
|
|
95
80
|
* Solid hairline rather than a dashed rule, and drawn at every tick including
|
|
96
81
|
* zero — the line under the bars is what makes them read as resting on a
|
|
@@ -213,14 +198,16 @@ export declare const ChartEmptyOverlay: import("react").ComponentType<Pick<impor
|
|
|
213
198
|
*/
|
|
214
199
|
export declare const ChartLegendRow: import("@linaria/react").StyledComponent<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & {
|
|
215
200
|
$inset: number;
|
|
201
|
+
$vertical?: boolean;
|
|
216
202
|
}>;
|
|
217
203
|
/**
|
|
218
204
|
* One legend entry, when the legend is interactive.
|
|
219
205
|
*
|
|
220
|
-
* A real `<button>` rather than a styled div
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
206
|
+
* A real `<button>` rather than a styled div so it sits in the tab order:
|
|
207
|
+
* focusing an entry previews its series exactly as hovering does, which is the
|
|
208
|
+
* one keyboard affordance the charts keep — the plot itself is `role="img"` and
|
|
209
|
+
* its marks are not in the accessibility tree. Activating it does nothing;
|
|
210
|
+
* isolation follows the pointer or the focus and releases with it.
|
|
224
211
|
*
|
|
225
212
|
* Shares the mark opacity ramp via `data-state`, so an entry recedes in step
|
|
226
213
|
* with the series it names.
|