@galaxy-io/dls 1.4.11 → 1.4.13

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.
@@ -13,6 +13,9 @@ 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
+ /** Tint the active category's full band, marking the hover position even
17
+ * where there is no data. @default true */
18
+ showCursor?: boolean;
16
19
  };
17
20
  /**
18
21
  * Bar chart with a three-level data model.
@@ -21,5 +24,5 @@ export type BarChartProps<TMetric extends string, TComponentKey extends string =
21
24
  * `bars` in a group render side by side, several `components` in a bar stack,
22
25
  * and a chart doing both at once needs no extra configuration.
23
26
  */
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, legendMaxItems, noTooltip, tooltipRenderer, isLoading, contentWhenEmpty, ariaLabel, ariaDescription, }: BarChartProps<TMetric, TComponentKey>) => import("react").JSX.Element;
27
+ declare const BarChart: <TMetric extends string, TComponentKey extends string = string>({ series, groups, width, height, fillWidth, fillHeight, aspectRatio, margin, normalization, showCursor, valueUnit, valueFormatter, labelFormatter, valueDomain, categoryLabelMode, categoryAxisTitle, valueAxisTitle, showGrid, showLegend, legendMaxItems, noTooltip, tooltipRenderer, isLoading, contentWhenEmpty, ariaLabel, ariaDescription, }: BarChartProps<TMetric, TComponentKey>) => import("react").JSX.Element;
25
28
  export default BarChart;
@@ -1,10 +1,10 @@
1
- import { BarChartNormalization, ChartKind, ChartTargetShape } from "./types.js";
1
+ import { BarChartNormalization, ChartKind, ChartMarkState, ChartTargetShape } from "./types.js";
2
2
  import { useSeriesColorResolver } from "./useSeriesColorResolver.js";
3
3
  import { useChartInteraction } from "./useChartInteraction.js";
4
4
  import { useCartesianChartLayout } from "./useCartesianChartLayout.js";
5
5
  import { getBarLegendItems } from "./barChartLegend.js";
6
6
  import { buildBarChartGeometry, getBarValueDomain, roundedRectPath } from "./barChartGeometry.js";
7
- import { ChartBarPath } from "./ChartPrimitives.js";
7
+ import { ChartBarPath, ChartCursorBand } from "./ChartPrimitives.js";
8
8
  import ChartFrame from "./ChartFrame.js";
9
9
  import { ChartCategoryAxis, ChartValueAxis } from "./ChartAxis.js";
10
10
  import { useCallback, useMemo, useRef } from "react";
@@ -17,7 +17,7 @@ import { Fragment as Fragment$1, 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, legendMaxItems, noTooltip = false, tooltipRenderer, isLoading = false, contentWhenEmpty, ariaLabel, ariaDescription }) => {
20
+ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRatio, margin, normalization = BarChartNormalization.NONE, showCursor = true, valueUnit, valueFormatter, labelFormatter, valueDomain, categoryLabelMode, categoryAxisTitle, valueAxisTitle, showGrid = true, showLegend = true, legendMaxItems, noTooltip = false, tooltipRenderer, isLoading = false, contentWhenEmpty, ariaLabel, ariaDescription }) => {
21
21
  const containerRef = useRef(null);
22
22
  const colors = useSeriesColorResolver(series);
23
23
  /**
@@ -106,9 +106,11 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
106
106
  categoryCount: geometry.bands.length,
107
107
  seriesKeys: legendKeys,
108
108
  categoryKeys,
109
- disabled: noTooltip || isLoading || isEmpty,
109
+ categoryMuteState: ChartMarkState.DIMMED,
110
+ isDisabled: noTooltip || isLoading || isEmpty,
110
111
  isLoading
111
112
  });
113
+ const activeBand = interaction.activeIndex === null ? null : geometry.bands[interaction.activeIndex] ?? null;
112
114
  const buildCategoryTooltip = useCallback((index) => {
113
115
  const band = geometry.bands[index];
114
116
  const group = groups[index];
@@ -142,7 +144,7 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
142
144
  width: band.width,
143
145
  height: band.height
144
146
  })), [geometry.bands]);
145
- return /* @__PURE__ */ jsx(ChartFrame, {
147
+ return /* @__PURE__ */ jsxs(ChartFrame, {
146
148
  containerRef,
147
149
  dimensions,
148
150
  fillWidth,
@@ -182,14 +184,19 @@ var BarChart = ({ series, groups, width, height, fillWidth, fillHeight, aspectRa
182
184
  showLegend,
183
185
  legendItems,
184
186
  legendMaxItems,
185
- children: geometry.rects.map((rect) => /* @__PURE__ */ jsx(ChartBarPath, {
187
+ children: [showCursor && activeBand && /* @__PURE__ */ jsx(ChartCursorBand, {
188
+ x: activeBand.x,
189
+ y: activeBand.y,
190
+ width: activeBand.width,
191
+ height: activeBand.height
192
+ }), geometry.rects.map((rect) => /* @__PURE__ */ jsx(ChartBarPath, {
186
193
  d: roundedRectPath(rect.x, rect.y, rect.width, rect.height, rect.radius, rect.corners),
187
194
  fill: rect.color,
188
195
  "data-state": interaction.getMarkState({
189
196
  categoryIndex: rect.groupIndex,
190
197
  seriesKey: isStacked ? rect.componentKey : rect.metric
191
198
  })
192
- }, rect.id))
199
+ }, rect.id))]
193
200
  });
194
201
  };
195
202
  //#endregion
@@ -7,21 +7,13 @@ import type { ChartInteraction } from "./useChartInteraction";
7
7
  * roles and no tab stops — the plot is `role="img"` and its accessible story is
8
8
  * the frame's label and description, while pointer users get the tooltip.
9
9
  *
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.
10
+ * Every category is hoverable, including one with nothing to show: the cursor
11
+ * still marks where the pointer is over an empty stretch of axis, and the
12
+ * tooltip opens with a "No data" body so the hover always gets an answer.
13
13
  */
14
14
  interface ChartCategoryTargetsProps {
15
15
  targets: ChartCategoryTarget[];
16
16
  interaction: ChartInteraction;
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
17
  }
26
- declare const ChartCategoryTargets: ({ targets, interaction, inertIndices, }: ChartCategoryTargetsProps) => import("react").JSX.Element;
18
+ declare const ChartCategoryTargets: ({ targets, interaction }: ChartCategoryTargetsProps) => import("react").JSX.Element;
27
19
  export default ChartCategoryTargets;
@@ -3,8 +3,7 @@ import { ChartHitTarget, ChartHitTargetPath } from "./ChartPrimitives.js";
3
3
  import { match } from "ts-pattern";
4
4
  import { Fragment, jsx } from "react/jsx-runtime";
5
5
  //#region src/charts/ChartCategoryTargets.tsx
6
- var ChartCategoryTargets = ({ targets, interaction, inertIndices }) => /* @__PURE__ */ jsx(Fragment, { children: targets.map((target, index) => {
7
- if (inertIndices?.has(index)) return null;
6
+ var ChartCategoryTargets = ({ targets, interaction }) => /* @__PURE__ */ jsx(Fragment, { children: targets.map((target, index) => {
8
7
  const shared = {
9
8
  onMouseEnter: () => interaction.onCategoryEnter(index),
10
9
  onMouseLeave: () => interaction.onCategoryLeave()
@@ -70,10 +70,9 @@ export interface ChartFrameProps {
70
70
  /**
71
71
  * Builds one category's tooltip, in plot coordinates.
72
72
  *
73
- * Taken as a function rather than a finished model because the frame needs it
74
- * twice: once for the category under the pointer, and once per category to
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.
73
+ * A rowless model means "no data here": the category stays hoverable and
74
+ * the built-in tooltip renders it with a "No data" body. A custom
75
+ * {@link tooltipRenderer} never receives a rowless model.
77
76
  *
78
77
  * Must be stable; memoize it at the call site.
79
78
  */
@@ -23,11 +23,18 @@ var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction
23
23
  * same situation, which is the drift this removes.
24
24
  */
25
25
  const resolvedAriaLabel = ariaLabel ?? match(kind).with(ChartKind.PIE, () => `Pie chart with ${categoryCount} slices`).with(ChartKind.BAR, () => `Bar chart with ${categoryCount} categories and ${legendItems.length} series`).with(ChartKind.LINE, () => `Line chart with ${categoryCount} categories and ${legendItems.length} series`).exhaustive();
26
- const tooltipModel = useMemo(() => noTooltip || !interaction.hasLocalHover || interaction.activeIndex === null ? null : buildCategoryTooltip(interaction.activeIndex), [
26
+ const tooltipModel = useMemo(() => {
27
+ if (noTooltip || !interaction.showTooltip || interaction.activeIndex === null) return null;
28
+ const model = buildCategoryTooltip(interaction.activeIndex);
29
+ if (model === null) return null;
30
+ if (model.rows.length === 0 && tooltipRenderer !== void 0) return null;
31
+ return model;
32
+ }, [
27
33
  noTooltip,
28
34
  buildCategoryTooltip,
29
35
  interaction.activeIndex,
30
- interaction.hasLocalHover
36
+ interaction.showTooltip,
37
+ tooltipRenderer
31
38
  ]);
32
39
  /**
33
40
  * Plot space → container space, applied once, here.
@@ -48,22 +55,6 @@ var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction
48
55
  margin.left,
49
56
  margin.top
50
57
  ]);
51
- /**
52
- * Categories whose tooltip would have no rows.
53
- *
54
- * Decided here — from the same builder that feeds the visible tooltip — so
55
- * "no data at this X" means exactly one thing in every chart: an all-zero
56
- * bar group and an all-null line column both produce a rowless model, and
57
- * neither should be hoverable. Their targets are simply not rendered.
58
- */
59
- const inertIndices = useMemo(() => {
60
- const inert = /* @__PURE__ */ new Set();
61
- (categoryTargets ?? []).forEach((_, index) => {
62
- const model = buildCategoryTooltip(index);
63
- if (!model || model.rows.length === 0) inert.add(index);
64
- });
65
- return inert;
66
- }, [categoryTargets, buildCategoryTooltip]);
67
58
  const hasTargets = isMeasured && !noTooltip && !isLoading && !isEmpty && (categoryTargets?.length ?? 0) > 0;
68
59
  const legendRight = legendPlacement === ChartLegendPlacement.RIGHT;
69
60
  return /* @__PURE__ */ jsxs(ChartRoot, {
@@ -96,8 +87,7 @@ var ChartFrame = ({ containerRef, dimensions, fillWidth, fillHeight, interaction
96
87
  transform: categoryTargetsTransform,
97
88
  children: /* @__PURE__ */ jsx(ChartCategoryTargets, {
98
89
  targets: categoryTargets,
99
- interaction,
100
- inertIndices
90
+ interaction
101
91
  })
102
92
  })
103
93
  ]
@@ -2,7 +2,6 @@ import Text, { TextSize, TextVariant } from "../text/Text.js";
2
2
  import Tooltip, { TooltipPosition, TooltipVariant } from "../tooltip/Tooltip.js";
3
3
  import Circle from "../shapes/Circle.js";
4
4
  import { ChartMarkState } from "./types.js";
5
- import "./constants.js";
6
5
  import { ChartLegendItemButton, ChartLegendItemStatic, ChartLegendMeasure, ChartLegendOverflowList, ChartLegendRow } from "./ChartPrimitives.js";
7
6
  import { useCallback, useLayoutEffect, useRef, useState } from "react";
8
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -38,14 +37,13 @@ var ChartLegend = ({ items, inset, hoveredKey = null, vertical = false, vertical
38
37
  const rendered = Array.from(measure.children);
39
38
  const trigger = rendered.pop();
40
39
  if (!trigger) return;
41
- const gap = vertical ? 8 : 16;
42
40
  const available = vertical ? verticalExtent || Number.POSITIVE_INFINITY : row.clientWidth - inset;
43
41
  const sizeOf = (el) => {
44
42
  const rect = el.getBoundingClientRect();
45
43
  return Math.ceil(vertical ? rect.height : rect.width);
46
44
  };
47
45
  const sizes = rendered.map(sizeOf);
48
- if (sizes.reduce((sum, size, i) => sum + size + (i > 0 ? gap : 0), 0) <= available) {
46
+ if (sizes.reduce((sum, size) => sum + size, 0) <= available) {
49
47
  setFitCount(sizes.length);
50
48
  return;
51
49
  }
@@ -53,8 +51,8 @@ var ChartLegend = ({ items, inset, hoveredKey = null, vertical = false, vertical
53
51
  let used = 0;
54
52
  let count = 0;
55
53
  for (const [i, size] of sizes.entries()) {
56
- used += size + (i > 0 ? gap : 0);
57
- if (used + gap + triggerSize > available) break;
54
+ used += size;
55
+ if (used + triggerSize > available) break;
58
56
  count = i + 1;
59
57
  }
60
58
  setFitCount(Math.max(1, count));
@@ -80,7 +78,7 @@ var ChartLegend = ({ items, inset, hoveredKey = null, vertical = false, vertical
80
78
  if (items.length === 0) return null;
81
79
  const isInteractive = Boolean(onItemEnter);
82
80
  const activeKey = hoveredKey;
83
- const renderItem = (item) => {
81
+ const renderItem = (item, verticalPadding) => {
84
82
  const state = activeKey === null || item.key === activeKey ? ChartMarkState.ACTIVE : ChartMarkState.MUTED;
85
83
  const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Circle, {
86
84
  size: 8,
@@ -90,11 +88,13 @@ var ChartLegend = ({ items, inset, hoveredKey = null, vertical = false, vertical
90
88
  children: item.label
91
89
  })] });
92
90
  if (!isInteractive) return /* @__PURE__ */ jsx(ChartLegendItemStatic, {
91
+ $vertical: verticalPadding,
93
92
  "data-state": state,
94
93
  children: content
95
94
  }, item.key);
96
95
  return /* @__PURE__ */ jsx(ChartLegendItemButton, {
97
96
  type: "button",
97
+ $vertical: verticalPadding,
98
98
  "data-state": state,
99
99
  onMouseEnter: () => onItemEnter?.(item.key),
100
100
  onMouseLeave: () => onItemLeave?.(),
@@ -124,26 +124,33 @@ var ChartLegend = ({ items, inset, hoveredKey = null, vertical = false, vertical
124
124
  ref: measureRef,
125
125
  $vertical: vertical,
126
126
  "aria-hidden": "true",
127
- children: [items.map((item) => /* @__PURE__ */ jsxs(ChartLegendItemStatic, { children: [/* @__PURE__ */ jsx(Circle, {
128
- size: 8,
129
- hex: item.color
130
- }), /* @__PURE__ */ jsx(Text, {
131
- size: TextSize.BODY_SM,
132
- children: item.label
133
- })] }, item.key)), /* @__PURE__ */ jsx(ChartLegendItemStatic, { children: /* @__PURE__ */ jsx(Text, {
134
- size: TextSize.BODY_SM,
135
- variant: TextVariant.SECONDARY,
136
- children: `+${items.length - 1} more`
137
- }) })]
127
+ children: [items.map((item) => /* @__PURE__ */ jsxs(ChartLegendItemStatic, {
128
+ $vertical: vertical,
129
+ children: [/* @__PURE__ */ jsx(Circle, {
130
+ size: 8,
131
+ hex: item.color
132
+ }), /* @__PURE__ */ jsx(Text, {
133
+ size: TextSize.BODY_SM,
134
+ children: item.label
135
+ })]
136
+ }, item.key)), /* @__PURE__ */ jsx(ChartLegendItemStatic, {
137
+ $vertical: vertical,
138
+ children: /* @__PURE__ */ jsx(Text, {
139
+ size: TextSize.BODY_SM,
140
+ variant: TextVariant.SECONDARY,
141
+ children: `+${items.length - 1} more`
142
+ })
143
+ })]
138
144
  }),
139
- inlineItems.map(renderItem),
145
+ inlineItems.map((item) => renderItem(item, vertical)),
140
146
  overflowItems.length > 0 && /* @__PURE__ */ jsx(Tooltip, {
141
147
  isInteractive: true,
142
148
  position: vertical ? TooltipPosition.RIGHT : TooltipPosition.TOP,
143
149
  variant: TooltipVariant.TERTIARY,
144
- body: /* @__PURE__ */ jsx(ChartLegendOverflowList, { children: overflowItems.map(renderItem) }),
150
+ body: /* @__PURE__ */ jsx(ChartLegendOverflowList, { children: overflowItems.map((item) => renderItem(item, true)) }),
145
151
  children: /* @__PURE__ */ jsx(ChartLegendItemButton, {
146
152
  type: "button",
153
+ $vertical: vertical,
147
154
  "data-state": triggerState,
148
155
  children: /* @__PURE__ */ jsx(Text, {
149
156
  size: TextSize.BODY_SM,
@@ -111,6 +111,29 @@ export declare const ChartCursorLine: import("react").ComponentType<Pick<import(
111
111
  } & {
112
112
  as?: React.ElementType;
113
113
  }>, {}>;
114
+ /**
115
+ * Full-height tint over the hovered category's band on a bar chart — the bar
116
+ * counterpart to {@link ChartCursorLine}. A rule reads oddly threaded through
117
+ * wide filled marks; a quiet band behind them marks the same position without
118
+ * touching them. 8% of the foreground, so it survives both themes.
119
+ */
120
+ export declare const ChartCursorBand: import("react").ComponentType<Pick<import("react").SVGProps<SVGRectElement> & {
121
+ theme: import("../theme").Theme;
122
+ } & {
123
+ as?: React.ElementType;
124
+ }, "as" | keyof import("react").SVGProps<SVGRectElement>> & {
125
+ theme?: import("@callstack/react-theme-provider").$DeepPartial<import("../theme").Theme> | undefined;
126
+ }> & import("@callstack/react-theme-provider/typings/hoist-non-react-statics").NonReactStatics<import("react").ComponentType<import("react").SVGProps<SVGRectElement> & {
127
+ theme: import("../theme").Theme;
128
+ } & {
129
+ as?: React.ElementType;
130
+ }> & {
131
+ __wyw_meta: unknown;
132
+ } & import("react").FunctionComponent<import("react").SVGProps<SVGRectElement> & {
133
+ theme: import("../theme").Theme;
134
+ } & {
135
+ as?: React.ElementType;
136
+ }>, {}>;
114
137
  export declare const ChartAxisLabelBox: import("@linaria/react").StyledComponent<import("react").SVGProps<SVGForeignObjectElement> & Record<never, unknown>>;
115
138
  /**
116
139
  * Positioned from coordinates already clamped to the chart box.
@@ -235,7 +258,18 @@ export declare const ChartLegendOverflowList: import("@linaria/react").StyledCom
235
258
  *
236
259
  * Shares the mark opacity ramp via `data-state`, so an entry recedes in step
237
260
  * with the series it names.
261
+ *
262
+ * The trailing padding is the inter-entry spacing — deliberately padding on
263
+ * the entry rather than a gap on the container, so the hover surfaces of
264
+ * adjacent entries touch and a sweep hands the isolation directly from one
265
+ * series to the next. Trailing only, so the first entry stays flush with the
266
+ * plot's left edge (or the column's top).
238
267
  */
239
- export declare const ChartLegendItemButton: import("@linaria/react").StyledComponent<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement> & Record<never, unknown>>;
240
- /** The same row, when the legend is inert — no button semantics to announce. */
241
- export declare const ChartLegendItemStatic: import("@linaria/react").StyledComponent<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & Record<never, unknown>>;
268
+ export declare const ChartLegendItemButton: import("@linaria/react").StyledComponent<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement> & {
269
+ $vertical?: boolean;
270
+ }>;
271
+ /** The same row, when the legend is inert — no button semantics to announce.
272
+ * Carries the same trailing padding; see {@link ChartLegendItemButton}. */
273
+ export declare const ChartLegendItemStatic: import("@linaria/react").StyledComponent<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & {
274
+ $vertical?: boolean;
275
+ }>;
@@ -176,9 +176,22 @@ var ChartCursorLine = withTheme(/*#__PURE__*/ styled("line")({
176
176
  propsAsIs: true,
177
177
  vars: { "cblgiyf-0": [_exp16()] }
178
178
  }));
179
+ /**
180
+ * Full-height tint over the hovered category's band on a bar chart — the bar
181
+ * counterpart to {@link ChartCursorLine}. A rule reads oddly threaded through
182
+ * wide filled marks; a quiet band behind them marks the same position without
183
+ * touching them. 8% of the foreground, so it survives both themes.
184
+ */
185
+ var _exp17 = () => ({ theme }) => theme.color.opacity.bw8Alt;
186
+ var ChartCursorBand = withTheme(/*#__PURE__*/ styled("rect")({
187
+ name: "ChartCursorBand",
188
+ class: "c1lr03cc",
189
+ propsAsIs: true,
190
+ vars: { "c1lr03cc-0": [_exp17()] }
191
+ }));
179
192
  var ChartAxisLabelBox = /*#__PURE__*/ styled("foreignObject")({
180
193
  name: "ChartAxisLabelBox",
181
- class: "c1lr03cc",
194
+ class: "cizy1s8",
182
195
  propsAsIs: true
183
196
  });
184
197
  /**
@@ -188,21 +201,21 @@ var ChartAxisLabelBox = /*#__PURE__*/ styled("foreignObject")({
188
201
  * than teleporting, and it stays mounted while hidden so the fade can actually
189
202
  * run — unmounting on hide is why a fade-out never appears.
190
203
  */
191
- var _exp17 = () => ({ $x }) => `${$x}px`;
192
- var _exp18 = () => ({ $y }) => `${$y}px`;
193
- var _exp21 = () => ({ theme }) => theme.color.border.primary;
194
- var _exp22 = () => ({ theme }) => theme.color.background.tertiary;
195
- var _exp23 = () => ({ $isVisible }) => $isVisible ? 1 : 0;
204
+ var _exp18 = () => ({ $x }) => `${$x}px`;
205
+ var _exp19 = () => ({ $y }) => `${$y}px`;
206
+ var _exp22 = () => ({ theme }) => theme.color.border.primary;
207
+ var _exp23 = () => ({ theme }) => theme.color.background.tertiary;
208
+ var _exp24 = () => ({ $isVisible }) => $isVisible ? 1 : 0;
196
209
  var ChartTooltipPositioner = withTheme(/*#__PURE__*/ styled("div")({
197
210
  name: "ChartTooltipPositioner",
198
- class: "cizy1s8",
211
+ class: "c1ukq11d",
199
212
  propsAsIs: false,
200
213
  vars: {
201
- "cizy1s8-0": [_exp17()],
202
- "cizy1s8-1": [_exp18()],
203
- "cizy1s8-2": [_exp21()],
204
- "cizy1s8-3": [_exp22()],
205
- "cizy1s8-4": [_exp23()]
214
+ "c1ukq11d-0": [_exp18()],
215
+ "c1ukq11d-1": [_exp19()],
216
+ "c1ukq11d-2": [_exp22()],
217
+ "c1ukq11d-3": [_exp23()],
218
+ "c1ukq11d-4": [_exp24()]
206
219
  }
207
220
  }));
208
221
  /**
@@ -216,19 +229,19 @@ var ChartTooltipPositioner = withTheme(/*#__PURE__*/ styled("div")({
216
229
  */
217
230
  var ChartTooltipGrid = /*#__PURE__*/ styled("div")({
218
231
  name: "ChartTooltipGrid",
219
- class: "c1ukq11d",
232
+ class: "cwcko2m",
220
233
  propsAsIs: false
221
234
  });
222
235
  /** Swatch + label. `min-width: 0` is what lets the label actually ellipsize. */
223
236
  var ChartTooltipLabelCell = /*#__PURE__*/ styled("div")({
224
237
  name: "ChartTooltipLabelCell",
225
- class: "cwcko2m",
238
+ class: "cqwhvyz",
226
239
  propsAsIs: false
227
240
  });
228
241
  /** Right-aligned and never wrapped — the value always shows in full. */
229
242
  var ChartTooltipValueCell = /*#__PURE__*/ styled("div")({
230
243
  name: "ChartTooltipValueCell",
231
- class: "cqwhvyz",
244
+ class: "c1iaray",
232
245
  propsAsIs: false
233
246
  });
234
247
  /**
@@ -239,41 +252,40 @@ var ChartTooltipValueCell = /*#__PURE__*/ styled("div")({
239
252
  * of the DLS. `pointer-events: none` keeps it from stealing hover from the arc
240
253
  * behind it.
241
254
  */
242
- var _exp27 = () => ({ $centerX }) => `${$centerX}px`;
243
- var _exp28 = () => ({ $centerY }) => `${$centerY}px`;
244
- var _exp30 = () => ({ $diameter }) => `${$diameter}px`;
255
+ var _exp28 = () => ({ $centerX }) => `${$centerX}px`;
256
+ var _exp29 = () => ({ $centerY }) => `${$centerY}px`;
257
+ var _exp31 = () => ({ $diameter }) => `${$diameter}px`;
245
258
  var ChartCenterBox = /*#__PURE__*/ styled("div")({
246
259
  name: "ChartCenterBox",
247
- class: "c1iaray",
260
+ class: "cz6jod1",
248
261
  propsAsIs: false,
249
262
  vars: {
250
- "c1iaray-0": [_exp27()],
251
- "c1iaray-1": [_exp28()],
252
- "c1iaray-2": [_exp30()]
263
+ "cz6jod1-0": [_exp28()],
264
+ "cz6jod1-1": [_exp29()],
265
+ "cz6jod1-2": [_exp31()]
253
266
  }
254
267
  });
255
268
  /**
256
269
  * Sits slightly above centre, over where the bars would be, so the axes stay
257
270
  * legible underneath.
258
271
  */
259
- var _exp31 = () => ({ theme }) => theme.color.border.primary;
260
- var _exp32 = () => ({ theme }) => theme.color.background.primary;
272
+ var _exp32 = () => ({ theme }) => theme.color.border.primary;
273
+ var _exp33 = () => ({ theme }) => theme.color.background.primary;
261
274
  var ChartEmptyOverlay = withTheme(/*#__PURE__*/ styled("div")({
262
275
  name: "ChartEmptyOverlay",
263
- class: "cz6jod1",
276
+ class: "c1de5mqk",
264
277
  propsAsIs: false,
265
278
  vars: {
266
- "cz6jod1-0": [_exp31()],
267
- "cz6jod1-1": [_exp32()]
279
+ "c1de5mqk-0": [_exp32()],
280
+ "c1de5mqk-1": [_exp33()]
268
281
  }
269
282
  }));
270
283
  /**
271
284
  * Aligns the legend under the plot rather than the value-axis gutter.
272
285
  */
273
- var _exp33 = () => ({ $vertical }) => $vertical ? "column" : "row";
274
- var _exp34 = () => ({ $vertical }) => $vertical ? "flex-start" : "center";
275
- var _exp35 = () => ({ $vertical }) => $vertical ? "center" : "flex-start";
276
- var _exp36 = () => ({ $vertical }) => $vertical ? `8px` : `16px`;
286
+ var _exp34 = () => ({ $vertical }) => $vertical ? "column" : "row";
287
+ var _exp35 = () => ({ $vertical }) => $vertical ? "flex-start" : "center";
288
+ var _exp36 = () => ({ $vertical }) => $vertical ? "center" : "flex-start";
277
289
  var _exp37 = () => ({ $vertical }) => $vertical ? "auto" : "0";
278
290
  var _exp38 = () => ({ $vertical }) => $vertical ? "0" : "100%";
279
291
  var _exp39 = () => ({ $vertical, $extent }) => $vertical && $extent ? `${$extent}px` : "auto";
@@ -281,18 +293,17 @@ var _exp40 = () => ({ $vertical }) => $vertical ? "0" : "10px";
281
293
  var _exp41 = () => ({ $inset }) => `${$inset}px`;
282
294
  var ChartLegendRow = /*#__PURE__*/ styled("div")({
283
295
  name: "ChartLegendRow",
284
- class: "c1de5mqk",
296
+ class: "cjirv6a",
285
297
  propsAsIs: false,
286
298
  vars: {
287
- "c1de5mqk-0": [_exp33()],
288
- "c1de5mqk-1": [_exp34()],
289
- "c1de5mqk-2": [_exp35()],
290
- "c1de5mqk-3": [_exp36()],
291
- "c1de5mqk-4": [_exp37()],
292
- "c1de5mqk-5": [_exp38()],
293
- "c1de5mqk-6": [_exp39()],
294
- "c1de5mqk-7": [_exp40()],
295
- "c1de5mqk-8": [_exp41()]
299
+ "cjirv6a-0": [_exp34()],
300
+ "cjirv6a-1": [_exp35()],
301
+ "cjirv6a-2": [_exp36()],
302
+ "cjirv6a-3": [_exp37()],
303
+ "cjirv6a-4": [_exp38()],
304
+ "cjirv6a-5": [_exp39()],
305
+ "cjirv6a-6": [_exp40()],
306
+ "cjirv6a-7": [_exp41()]
296
307
  }
297
308
  });
298
309
  /**
@@ -305,15 +316,13 @@ var ChartLegendRow = /*#__PURE__*/ styled("div")({
305
316
  */
306
317
  var _exp42 = () => ({ $vertical }) => $vertical ? "column" : "row";
307
318
  var _exp43 = () => ({ $vertical }) => $vertical ? "flex-start" : "center";
308
- var _exp44 = () => ({ $vertical }) => $vertical ? `8px` : `16px`;
309
319
  var ChartLegendMeasure = /*#__PURE__*/ styled("div")({
310
320
  name: "ChartLegendMeasure",
311
- class: "cjirv6a",
321
+ class: "c1armna5",
312
322
  propsAsIs: false,
313
323
  vars: {
314
- "cjirv6a-0": [_exp42()],
315
- "cjirv6a-1": [_exp43()],
316
- "cjirv6a-2": [_exp44()]
324
+ "c1armna5-0": [_exp42()],
325
+ "c1armna5-1": [_exp43()]
317
326
  }
318
327
  });
319
328
  /**
@@ -325,7 +334,7 @@ var ChartLegendMeasure = /*#__PURE__*/ styled("div")({
325
334
  */
326
335
  var ChartLegendOverflowList = /*#__PURE__*/ styled("div")({
327
336
  name: "ChartLegendOverflowList",
328
- class: "c1armna5",
337
+ class: "cgd77rv",
329
338
  propsAsIs: false
330
339
  });
331
340
  /**
@@ -339,17 +348,28 @@ var ChartLegendOverflowList = /*#__PURE__*/ styled("div")({
339
348
  *
340
349
  * Shares the mark opacity ramp via `data-state`, so an entry recedes in step
341
350
  * with the series it names.
351
+ *
352
+ * The trailing padding is the inter-entry spacing — deliberately padding on
353
+ * the entry rather than a gap on the container, so the hover surfaces of
354
+ * adjacent entries touch and a sweep hands the isolation directly from one
355
+ * series to the next. Trailing only, so the first entry stays flush with the
356
+ * plot's left edge (or the column's top).
342
357
  */
358
+ var _exp45 = () => ({ $vertical }) => $vertical ? `0 0 8px 0` : `0 16px 0 0`;
343
359
  var ChartLegendItemButton = /*#__PURE__*/ styled("button")({
344
360
  name: "ChartLegendItemButton",
345
- class: "cgd77rv",
346
- propsAsIs: false
361
+ class: "cutidpi",
362
+ propsAsIs: false,
363
+ vars: { "cutidpi-0": [_exp45()] }
347
364
  });
348
- /** The same row, when the legend is inert — no button semantics to announce. */
365
+ /** The same row, when the legend is inert — no button semantics to announce.
366
+ * Carries the same trailing padding; see {@link ChartLegendItemButton}. */
367
+ var _exp47 = () => ({ $vertical }) => $vertical ? `0 0 8px 0` : `0 16px 0 0`;
349
368
  var ChartLegendItemStatic = /*#__PURE__*/ styled("div")({
350
369
  name: "ChartLegendItemStatic",
351
- class: "cutidpi",
352
- propsAsIs: false
370
+ class: "ccpczg",
371
+ propsAsIs: false,
372
+ vars: { "ccpczg-0": [_exp47()] }
353
373
  });
354
374
  //#endregion
355
- export { ChartArcPath, ChartAreaPath, ChartAxisLabelBox, ChartBarPath, ChartCenterBox, ChartCursorLine, ChartEmptyOverlay, ChartGridLine, ChartHitTarget, ChartHitTargetPath, ChartLegendItemButton, ChartLegendItemStatic, ChartLegendMeasure, ChartLegendOverflowList, ChartLegendRow, ChartLinePath, ChartPlotBox, ChartPointCircle, ChartRoot, ChartSvg, ChartTooltipGrid, ChartTooltipLabelCell, ChartTooltipPositioner, ChartTooltipValueCell };
375
+ export { ChartArcPath, ChartAreaPath, ChartAxisLabelBox, ChartBarPath, ChartCenterBox, ChartCursorBand, ChartCursorLine, ChartEmptyOverlay, ChartGridLine, ChartHitTarget, ChartHitTargetPath, ChartLegendItemButton, ChartLegendItemStatic, ChartLegendMeasure, ChartLegendOverflowList, ChartLegendRow, ChartLinePath, ChartPlotBox, ChartPointCircle, ChartRoot, ChartSvg, ChartTooltipGrid, ChartTooltipLabelCell, ChartTooltipPositioner, ChartTooltipValueCell };
@@ -36,7 +36,11 @@ var ChartTooltip = ({ model, containerWidth, containerHeight, anchorHalfWidth, p
36
36
  variant: TextVariant.TERTIARY,
37
37
  isEllipsis: true,
38
38
  children: displayed.label
39
- }), /* @__PURE__ */ jsx(ChartTooltipGrid, { children: displayed.rows.map((row) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(ChartTooltipLabelCell, { children: [/* @__PURE__ */ jsx(FlexItem, {
39
+ }), displayed.rows.length === 0 ? /* @__PURE__ */ jsx(Text, {
40
+ size: TextSize.BODY_SM,
41
+ variant: TextVariant.SECONDARY,
42
+ children: "No data"
43
+ }) : /* @__PURE__ */ jsx(ChartTooltipGrid, { children: displayed.rows.map((row) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(ChartTooltipLabelCell, { children: [/* @__PURE__ */ jsx(FlexItem, {
40
44
  shrink: 0,
41
45
  children: /* @__PURE__ */ jsx(Circle, {
42
46
  size: 8,
@@ -17,6 +17,8 @@ export interface DashboardContextValue {
17
17
  setActive: (entry: DashboardSyncEntry) => void;
18
18
  /** Clears only if the current entry belongs to `sourceId`. */
19
19
  clearActive: (sourceId: string) => void;
20
+ /** Followers open their own tooltip at the synced category. */
21
+ sharedTooltip: boolean;
20
22
  }
21
23
  export declare const DashboardContext: import("react").Context<DashboardContextValue | null>;
22
24
  /**
@@ -24,9 +26,13 @@ export declare const DashboardContext: import("react").Context<DashboardContextV
24
26
  *
25
27
  * Hovering a category in one chart shows the same category emphasized in every
26
28
  * sibling — matched by raw category label, so charts whose category sets only
27
- * partially overlap simply show nothing for the labels they lack. The tooltip
28
- * stays local to the chart under the pointer; siblings get the quiet emphasis
29
- * only (LineChart its cursor line and dots, BarChart its category muting).
29
+ * partially overlap simply show nothing for the labels they lack. By default
30
+ * the tooltip stays local to the chart under the pointer; siblings get the
31
+ * quiet emphasis only (LineChart its cursor line and dots, BarChart its band
32
+ * tint and gentle dim). `sharedTooltip` opts every synced chart into opening its
33
+ * own tooltip at the shared category — the tooltip anchors to the category's
34
+ * geometry, not the pointer, so a follower's opens exactly where a local
35
+ * hover's would.
30
36
  *
31
37
  * Scope, deliberately narrow:
32
38
  * - Only the category axis syncs. Legend (series) hover stays local.
@@ -43,5 +49,9 @@ export declare const DashboardContext: import("react").Context<DashboardContextV
43
49
  * across a chart re-renders the group a handful of times. No subscription or
44
50
  * selector machinery is warranted.
45
51
  */
46
- export declare const DashboardProvider: ({ children }: PropsWithChildren) => import("react").JSX.Element;
52
+ export interface DashboardProviderProps {
53
+ /** Every synced chart opens its own tooltip at the shared category. @default false */
54
+ sharedTooltip?: boolean;
55
+ }
56
+ export declare const DashboardProvider: ({ sharedTooltip, children, }: PropsWithChildren<DashboardProviderProps>) => import("react").JSX.Element;
47
57
  export default DashboardProvider;