@automattic/charts 4.8.0 → 4.9.0
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/CHANGELOG.md +14 -0
- package/dist/index.cjs +624 -228
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +58 -8
- package/dist/index.d.cts +42 -8
- package/dist/index.d.ts +42 -8
- package/dist/index.js +628 -232
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/charts/area-chart/area-chart.tsx +5 -2
- package/src/charts/area-chart/test/area-chart.test.tsx +23 -14
- package/src/charts/area-chart/test/tooltip-resolution.test.tsx +2 -2
- package/src/charts/area-chart/types.ts +2 -0
- package/src/charts/bar-chart/bar-chart.tsx +5 -2
- package/src/charts/bar-chart/test/bar-chart.test.tsx +82 -63
- package/src/charts/bar-chart/types.ts +2 -0
- package/src/charts/bar-list-chart/test/bar-list-chart.test.tsx +3 -1
- package/src/charts/heatmap-chart/heatmap-chart.module.scss +10 -4
- package/src/charts/heatmap-chart/heatmap-chart.tsx +144 -37
- package/src/charts/heatmap-chart/private/column-groups.ts +79 -8
- package/src/charts/heatmap-chart/private/fit-compact-cells.ts +72 -0
- package/src/charts/heatmap-chart/private/heatmap-legend.tsx +14 -2
- package/src/charts/heatmap-chart/private/index.ts +4 -2
- package/src/charts/heatmap-chart/test/column-groups.test.ts +41 -4
- package/src/charts/heatmap-chart/test/fit-compact-cells.test.ts +59 -0
- package/src/charts/heatmap-chart/test/heatmap-chart.test.tsx +132 -1
- package/src/charts/heatmap-chart/types.ts +2 -0
- package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +46 -4
- package/src/charts/leaderboard-chart/leaderboard-chart.tsx +37 -1
- package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +53 -0
- package/src/charts/leaderboard-chart/types.ts +6 -1
- package/src/charts/line-chart/line-chart.tsx +5 -2
- package/src/charts/line-chart/private/line-chart-annotation-label-popover.tsx +19 -9
- package/src/charts/line-chart/test/default-tooltip-formatting.test.tsx +1 -1
- package/src/charts/line-chart/test/line-chart.test.tsx +45 -35
- package/src/charts/line-chart/test/tooltip-resolution.test.tsx +2 -2
- package/src/charts/line-chart/types.ts +5 -3
- package/src/charts/pie-chart/pie-chart.tsx +149 -139
- package/src/charts/pie-chart/test/pie-chart.test.tsx +171 -0
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +122 -120
- package/src/charts/pie-semi-circle-chart/test/pie-semi-circle-chart.test.tsx +54 -0
- package/src/charts/private/chart-composition/use-chart-children.ts +11 -6
- package/src/charts/private/pie-keyboard-navigation/index.ts +4 -0
- package/src/charts/private/pie-keyboard-navigation/order-arcs-for-navigation.ts +10 -0
- package/src/charts/private/pie-keyboard-navigation/pie-keyboard-navigation.module.scss +16 -0
- package/src/charts/private/pie-keyboard-navigation/pie-selection-announcement.tsx +14 -0
- package/src/charts/private/pie-keyboard-navigation/pie-selection-output.tsx +82 -0
- package/src/charts/private/pie-keyboard-navigation/pie-tooltip.tsx +44 -0
- package/src/charts/private/pie-keyboard-navigation/selected-segment-ring.tsx +47 -0
- package/src/charts/private/pie-keyboard-navigation/test/order-arcs-for-navigation.test.ts +34 -0
- package/src/charts/private/pie-keyboard-navigation/test/selected-segment-ring.test.ts +14 -0
- package/src/charts/private/pie-keyboard-navigation/use-pie-keyboard-navigation.ts +139 -0
- package/src/charts/private/x-zoom/test/x-zoom.test.tsx +3 -2
- package/src/components/tooltip/test/xy-chart-tooltip.test.tsx +20 -19
- package/src/components/tooltip/xy-chart-tooltip.tsx +3 -3
- package/src/types.ts +18 -2
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { AnimatedAreaSeries, AnimatedAreaStack, AreaSeries, Axis, BarGroup, BarS
|
|
|
4
4
|
import { __, _x, sprintf } from "@wordpress/i18n";
|
|
5
5
|
import clsx from "clsx";
|
|
6
6
|
import * as React from "react";
|
|
7
|
-
import { Children, Fragment, createContext, createContext as createContext$1, createElement, forwardRef, forwardRef as forwardRef$1, isValidElement, memo, useCallback, useCallback as useCallback$1, useContext, useContext as useContext$1, useEffect, useEffect as useEffect$1, useId, useImperativeHandle, useLayoutEffect, useMemo, useMemo as useMemo$1, useRef, useRef as useRef$1, useState, useState as useState$1 } from "react";
|
|
7
|
+
import { Children, Fragment, createContext, createContext as createContext$1, createElement, forwardRef, forwardRef as forwardRef$1, isValidElement, memo, useCallback, useCallback as useCallback$1, useContext, useContext as useContext$1, useEffect, useEffect as useEffect$1, useId, useImperativeHandle, useLayoutEffect, useMemo, useMemo as useMemo$1, useRef, useRef as useRef$1, useState, useState as useState$1, version } from "react";
|
|
8
8
|
import { differenceInHours, differenceInYears, isValid, parse, parseISO } from "date-fns";
|
|
9
9
|
import { tzOffset } from "@date-fns/tz";
|
|
10
10
|
import { Text, getStringWidth } from "@visx/text";
|
|
@@ -15,9 +15,9 @@ import { useTooltip } from "@visx/tooltip";
|
|
|
15
15
|
import { createScale, getTicks, scaleBand, scaleCanBeZeroed, scaleOrdinal, scaleTime } from "@visx/scale";
|
|
16
16
|
import { Group } from "@visx/group";
|
|
17
17
|
import { LegendItem, LegendLabel, LegendOrdinal, LegendShape } from "@visx/legend";
|
|
18
|
-
import { IconButton, Stack, Text as Text$1 } from "@wordpress/ui";
|
|
18
|
+
import { IconButton, Stack, Text as Text$1, VisuallyHidden } from "@wordpress/ui";
|
|
19
19
|
import { ThemeProvider } from "@wordpress/theme";
|
|
20
|
-
import { createPortal } from "react-dom";
|
|
20
|
+
import { createPortal, flushSync } from "react-dom";
|
|
21
21
|
import { LinearGradient } from "@visx/gradient";
|
|
22
22
|
import { curveCatmullRom, curveLinear, curveMonotoneX } from "@visx/curve";
|
|
23
23
|
import { useParentSize } from "@visx/responsive";
|
|
@@ -30,7 +30,7 @@ import { __assign } from "tslib";
|
|
|
30
30
|
import "@babel/runtime/helpers/esm/extends";
|
|
31
31
|
import "@babel/runtime/helpers/extends";
|
|
32
32
|
import { Icon, chevronRight } from "@wordpress/icons";
|
|
33
|
-
import {
|
|
33
|
+
import { arc, pie } from "@visx/shape";
|
|
34
34
|
//#region \0rolldown/runtime.js
|
|
35
35
|
var __create = Object.create;
|
|
36
36
|
var __defProp = Object.defineProperty;
|
|
@@ -3080,7 +3080,7 @@ const XYChartTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocu
|
|
|
3080
3080
|
/** @deprecated Use `XYChartTooltip`. */
|
|
3081
3081
|
const AccessibleTooltip = XYChartTooltip;
|
|
3082
3082
|
const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating, setIsNavigating, chartRef, totalPoints, onActivate, preventTooltipScroll = false, visibleSeriesKey }) => {
|
|
3083
|
-
const getChartRoot = useCallback(() => chartRef.current?.closest("[role=\"
|
|
3083
|
+
const getChartRoot = useCallback(() => chartRef.current?.closest("[role=\"application\"]") ?? chartRef.current, [chartRef]);
|
|
3084
3084
|
const focusWithoutScrollIfNeeded = useCallback((element) => {
|
|
3085
3085
|
if (preventTooltipScroll) element?.focus({ preventScroll: true });
|
|
3086
3086
|
else element?.focus();
|
|
@@ -3295,11 +3295,13 @@ function useChartChildren(children, chartType) {
|
|
|
3295
3295
|
}
|
|
3296
3296
|
const displayName = child.type?.displayName;
|
|
3297
3297
|
if (displayName === `${chartType}.SVG` || displayName === "Chart.SVG") {
|
|
3298
|
-
|
|
3298
|
+
const { children: svgChildren } = child.props ?? {};
|
|
3299
|
+
if (svgChildren) Children.forEach(svgChildren, (svgChild) => {
|
|
3299
3300
|
svg.push(svgChild);
|
|
3300
3301
|
});
|
|
3301
3302
|
} else if (displayName === `${chartType}.HTML` || displayName === "Chart.HTML") {
|
|
3302
|
-
|
|
3303
|
+
const { children: htmlChildren } = child.props ?? {};
|
|
3304
|
+
if (htmlChildren) Children.forEach(htmlChildren, (htmlChild) => {
|
|
3303
3305
|
html.push(htmlChild);
|
|
3304
3306
|
});
|
|
3305
3307
|
} else if (child.type === Group) svg.push(child);
|
|
@@ -4121,6 +4123,7 @@ var line_chart_module_default = {
|
|
|
4121
4123
|
"line-chart--animated": "a8ccharts-inuQka-line-chart--animated",
|
|
4122
4124
|
"rise": "a8ccharts-inuQka-rise"
|
|
4123
4125
|
};
|
|
4126
|
+
const isReact18 = version.startsWith("18.");
|
|
4124
4127
|
const CloseIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
4125
4128
|
width: "16",
|
|
4126
4129
|
height: "16",
|
|
@@ -4163,7 +4166,7 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
|
|
|
4163
4166
|
className: line_chart_module_default["line-chart__annotation-label"],
|
|
4164
4167
|
children: [/* @__PURE__ */ jsx("button", {
|
|
4165
4168
|
ref: buttonRef,
|
|
4166
|
-
popovertarget: popoverId,
|
|
4169
|
+
...isReact18 ? { popovertarget: popoverId } : { popoverTarget: popoverId },
|
|
4167
4170
|
className: line_chart_module_default["line-chart__annotation-label-trigger-button"],
|
|
4168
4171
|
style: {
|
|
4169
4172
|
width: `44px`,
|
|
@@ -4191,8 +4194,13 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
|
|
|
4191
4194
|
subtitle
|
|
4192
4195
|
})
|
|
4193
4196
|
}), /* @__PURE__ */ jsx("button", {
|
|
4194
|
-
|
|
4195
|
-
|
|
4197
|
+
...isReact18 ? {
|
|
4198
|
+
popovertarget: popoverId,
|
|
4199
|
+
popovertargetaction: "hide"
|
|
4200
|
+
} : {
|
|
4201
|
+
popoverTarget: popoverId,
|
|
4202
|
+
popoverTargetAction: "hide"
|
|
4203
|
+
},
|
|
4196
4204
|
className: line_chart_module_default["line-chart__annotation-label-popover-close-button"],
|
|
4197
4205
|
"aria-label": __("Close", "jetpack-charts"),
|
|
4198
4206
|
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
@@ -4714,7 +4722,7 @@ const LineChartScalesRef = ({ chartRef, width, height, margin }) => {
|
|
|
4714
4722
|
]);
|
|
4715
4723
|
return null;
|
|
4716
4724
|
};
|
|
4717
|
-
const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, renderGlyph = defaultRenderGlyph, glyphStyle = {}, withLegendGlyph = false, withGradientFill = false, smoothing = true, curveType, renderTooltip = renderDefaultTooltip, tooltipPlacement, tooltipStyle, withStartGlyphs = false, withEndGlyphs = false, animation, options = {}, onPointerDown = void 0, onPointerUp = void 0, onPointerMove = void 0, onPointerOut = void 0, onDatumActivate = void 0, zoomable = false, rescaleYOnVisibilityChange = true, defaultHiddenSeries, children, gridVisibility, gap = "md" }, ref) => {
|
|
4725
|
+
const LineChartInternal = forwardRef(({ data, ariaLabel, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, renderGlyph = defaultRenderGlyph, glyphStyle = {}, withLegendGlyph = false, withGradientFill = false, smoothing = true, curveType, renderTooltip = renderDefaultTooltip, tooltipPlacement, tooltipStyle, withStartGlyphs = false, withEndGlyphs = false, animation, options = {}, onPointerDown = void 0, onPointerUp = void 0, onPointerMove = void 0, onPointerOut = void 0, onDatumActivate = void 0, zoomable = false, rescaleYOnVisibilityChange = true, defaultHiddenSeries, children, gridVisibility, gap = "md" }, ref) => {
|
|
4718
4726
|
const legendInteractive = legend.interactive ?? false;
|
|
4719
4727
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
4720
4728
|
const legendComparisonItem = legend.comparisonItem ?? false;
|
|
@@ -4982,8 +4990,8 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4982
4990
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
4983
4991
|
return /* @__PURE__ */ jsx("div", {
|
|
4984
4992
|
ref: chartRef,
|
|
4985
|
-
role: "
|
|
4986
|
-
"aria-label": __("Line chart", "jetpack-charts"),
|
|
4993
|
+
role: "application",
|
|
4994
|
+
"aria-label": ariaLabel ?? __("Line chart", "jetpack-charts"),
|
|
4987
4995
|
tabIndex: 0,
|
|
4988
4996
|
onKeyDown: onChartKeyDown,
|
|
4989
4997
|
onFocus: onChartFocus,
|
|
@@ -4991,6 +4999,7 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4991
4999
|
children: chartHeight > 0 && /* @__PURE__ */ jsxs("div", {
|
|
4992
5000
|
className: xy_plot_module_default["xy-plot"],
|
|
4993
5001
|
children: [zoomable && zoom.domain && /* @__PURE__ */ jsx(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ jsxs(XYChart, {
|
|
5002
|
+
accessibilityLabel: "",
|
|
4994
5003
|
theme,
|
|
4995
5004
|
width,
|
|
4996
5005
|
height: chartHeight,
|
|
@@ -5231,7 +5240,7 @@ const HoverGlyphs = ({ visibleSeries, stacked, stackOffset, getElementStyles, st
|
|
|
5231
5240
|
};
|
|
5232
5241
|
//#endregion
|
|
5233
5242
|
//#region src/charts/area-chart/area-chart.tsx
|
|
5234
|
-
const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, stacked = true, stackOffset = "none", smoothing = true, curveType, fillOpacity, withStroke, renderTooltip = renderDefaultTooltip, animation, options = {}, onPointerDown, onPointerUp, onPointerMove, onPointerOut, zoomable = false, rescaleYOnVisibilityChange = true, defaultHiddenSeries, children, gridVisibility, gap = "md" }, ref) => {
|
|
5243
|
+
const AreaChartInternal = forwardRef(({ data, ariaLabel, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, stacked = true, stackOffset = "none", smoothing = true, curveType, fillOpacity, withStroke, renderTooltip = renderDefaultTooltip, animation, options = {}, onPointerDown, onPointerUp, onPointerMove, onPointerOut, zoomable = false, rescaleYOnVisibilityChange = true, defaultHiddenSeries, children, gridVisibility, gap = "md" }, ref) => {
|
|
5235
5244
|
const legendInteractive = legend.interactive ?? false;
|
|
5236
5245
|
const legendShape = legend.shape ?? "rect";
|
|
5237
5246
|
const legendPosition = legend.position ?? "bottom";
|
|
@@ -5502,8 +5511,8 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
5502
5511
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
5503
5512
|
return /* @__PURE__ */ jsx("div", {
|
|
5504
5513
|
ref: chartRef,
|
|
5505
|
-
role: "
|
|
5506
|
-
"aria-label": __("Area chart", "jetpack-charts"),
|
|
5514
|
+
role: "application",
|
|
5515
|
+
"aria-label": ariaLabel ?? __("Area chart", "jetpack-charts"),
|
|
5507
5516
|
tabIndex: 0,
|
|
5508
5517
|
onKeyDown: onChartKeyDown,
|
|
5509
5518
|
onFocus: onChartFocus,
|
|
@@ -5511,6 +5520,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
5511
5520
|
children: chartHeight > 0 && /* @__PURE__ */ jsxs("div", {
|
|
5512
5521
|
className: xy_plot_module_default["xy-plot"],
|
|
5513
5522
|
children: [zoomable && zoom.domain && /* @__PURE__ */ jsx(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ jsxs(XYChart, {
|
|
5523
|
+
accessibilityLabel: "",
|
|
5514
5524
|
theme,
|
|
5515
5525
|
width,
|
|
5516
5526
|
height: chartHeight,
|
|
@@ -6363,7 +6373,7 @@ const renderTooltipRow = (label, value) => /* @__PURE__ */ jsx("div", {
|
|
|
6363
6373
|
className: bar_chart_module_default["bar-chart__tooltip-row"],
|
|
6364
6374
|
children: sprintf(__("%1$s: %2$s", "jetpack-charts"), label, value)
|
|
6365
6375
|
});
|
|
6366
|
-
const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, tooltipPlacement, tooltipAnchorTop, tooltipStyle, barClassName, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, withBandHighlight = false, onBandHighlightChange, defaultHiddenSeries, animation, children, gap = "md", onPointerDown, onPointerUp, onDatumActivate }) => {
|
|
6376
|
+
const BarChartInternal = ({ data, ariaLabel, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, tooltipPlacement, tooltipAnchorTop, tooltipStyle, barClassName, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, withBandHighlight = false, onBandHighlightChange, defaultHiddenSeries, animation, children, gap = "md", onPointerDown, onPointerUp, onDatumActivate }) => {
|
|
6367
6377
|
if (!withTooltips && (withBandHighlight || onBandHighlightChange)) warnOnce("bar-chart-band-highlight-without-tooltips", "BarChart: withBandHighlight and onBandHighlightChange require withTooltips.");
|
|
6368
6378
|
const legendInteractive = legend.interactive ?? false;
|
|
6369
6379
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
@@ -6671,9 +6681,9 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6671
6681
|
children: ({ contentHeight }) => {
|
|
6672
6682
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
6673
6683
|
return /* @__PURE__ */ jsx("div", {
|
|
6674
|
-
role: "
|
|
6684
|
+
role: "application",
|
|
6675
6685
|
ref: chartRef,
|
|
6676
|
-
"aria-label": __("Bar chart", "jetpack-charts"),
|
|
6686
|
+
"aria-label": ariaLabel ?? __("Bar chart", "jetpack-charts"),
|
|
6677
6687
|
tabIndex: 0,
|
|
6678
6688
|
onKeyDown: onChartKeyDown,
|
|
6679
6689
|
onFocus: onChartFocus,
|
|
@@ -6681,6 +6691,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6681
6691
|
children: chartHeight > 0 && /* @__PURE__ */ jsx("div", {
|
|
6682
6692
|
className: xy_plot_module_default["xy-plot"],
|
|
6683
6693
|
children: /* @__PURE__ */ jsxs(XYChart, {
|
|
6694
|
+
accessibilityLabel: "",
|
|
6684
6695
|
theme,
|
|
6685
6696
|
width,
|
|
6686
6697
|
height: chartHeight,
|
|
@@ -7686,6 +7697,7 @@ var heatmap_chart_module_default = {
|
|
|
7686
7697
|
"heatmap-chart__legend-label": "a8ccharts-O3YMOW-heatmap-chart__legend-label",
|
|
7687
7698
|
"heatmap-chart__legend-scale--bar": "a8ccharts-O3YMOW-heatmap-chart__legend-scale--bar",
|
|
7688
7699
|
"heatmap-chart__legend-swatch": "a8ccharts-O3YMOW-heatmap-chart__legend-swatch",
|
|
7700
|
+
"heatmap-chart__legend-swatch--empty": "a8ccharts-O3YMOW-heatmap-chart__legend-swatch--empty",
|
|
7689
7701
|
"heatmap-chart__row": "a8ccharts-O3YMOW-heatmap-chart__row",
|
|
7690
7702
|
"heatmap-chart__row-label": "a8ccharts-O3YMOW-heatmap-chart__row-label",
|
|
7691
7703
|
"heatmap-chart--height-capped": "a8ccharts-O3YMOW-heatmap-chart--height-capped"
|
|
@@ -7783,8 +7795,9 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7783
7795
|
const context = useContext(HeatmapContext);
|
|
7784
7796
|
const { legend } = useGlobalChartsTheme();
|
|
7785
7797
|
if (!context) return null;
|
|
7786
|
-
const { fillVars } = context;
|
|
7798
|
+
const { extent, fillVars } = context;
|
|
7787
7799
|
const labelStyle = legend.labelStyles;
|
|
7800
|
+
const showsEmptyCell = isEmptyValue(0, extent);
|
|
7788
7801
|
return /* @__PURE__ */ jsxs(Stack, {
|
|
7789
7802
|
direction: "row",
|
|
7790
7803
|
gap: "xs",
|
|
@@ -7796,12 +7809,12 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7796
7809
|
style: labelStyle,
|
|
7797
7810
|
children: lessLabel ?? __("Less", "jetpack-charts")
|
|
7798
7811
|
}),
|
|
7799
|
-
/* @__PURE__ */
|
|
7812
|
+
/* @__PURE__ */ jsxs(Stack, {
|
|
7800
7813
|
direction: "row",
|
|
7801
7814
|
gap: variant === "bar" ? void 0 : "xs",
|
|
7802
7815
|
"aria-hidden": "true",
|
|
7803
7816
|
className: variant === "bar" ? heatmap_chart_module_default["heatmap-chart__legend-scale--bar"] : void 0,
|
|
7804
|
-
children: Array.from({ length: steps }, (_, index) => {
|
|
7817
|
+
children: [showsEmptyCell && /* @__PURE__ */ jsx("span", { className: clsx(heatmap_chart_module_default["heatmap-chart__legend-swatch"], heatmap_chart_module_default["heatmap-chart__legend-swatch--empty"]) }), Array.from({ length: steps }, (_, index) => {
|
|
7805
7818
|
const intensity = steps <= 1 ? 1 : index / (steps - 1);
|
|
7806
7819
|
return /* @__PURE__ */ jsx("span", {
|
|
7807
7820
|
className: heatmap_chart_module_default["heatmap-chart__legend-swatch"],
|
|
@@ -7810,7 +7823,7 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7810
7823
|
"--a8c-charts-heatmap-cell-intensity": intensity
|
|
7811
7824
|
}
|
|
7812
7825
|
}, index);
|
|
7813
|
-
})
|
|
7826
|
+
})]
|
|
7814
7827
|
}),
|
|
7815
7828
|
/* @__PURE__ */ jsx(Text$1, {
|
|
7816
7829
|
variant: "body-sm",
|
|
@@ -7836,9 +7849,11 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7836
7849
|
const ungrouped = () => ({
|
|
7837
7850
|
columns: Array.from({ length: columnCount }, (_, index) => ({
|
|
7838
7851
|
line: firstLine + index,
|
|
7852
|
+
band: 0,
|
|
7839
7853
|
gapBefore: false
|
|
7840
7854
|
})),
|
|
7841
|
-
groups: []
|
|
7855
|
+
groups: [],
|
|
7856
|
+
bands: 1
|
|
7842
7857
|
});
|
|
7843
7858
|
if (!groups || groups.length === 0 || columnCount === 0) return ungrouped();
|
|
7844
7859
|
const spans = groups.map((group) => group.span);
|
|
@@ -7854,11 +7869,13 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7854
7869
|
if (groupIndex > 0) line += 1;
|
|
7855
7870
|
laidOut.push({
|
|
7856
7871
|
...group,
|
|
7857
|
-
line
|
|
7872
|
+
line,
|
|
7873
|
+
band: 0
|
|
7858
7874
|
});
|
|
7859
7875
|
for (let offset = 0; offset < group.span; offset++) {
|
|
7860
7876
|
columns.push({
|
|
7861
7877
|
line,
|
|
7878
|
+
band: 0,
|
|
7862
7879
|
gapBefore: groupIndex > 0 && offset === 0,
|
|
7863
7880
|
group: groupIndex
|
|
7864
7881
|
});
|
|
@@ -7868,13 +7885,99 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7868
7885
|
while (columns.length < columnCount) {
|
|
7869
7886
|
columns.push({
|
|
7870
7887
|
line,
|
|
7888
|
+
band: 0,
|
|
7871
7889
|
gapBefore: false
|
|
7872
7890
|
});
|
|
7873
7891
|
line += 1;
|
|
7874
7892
|
}
|
|
7875
7893
|
return {
|
|
7876
7894
|
columns,
|
|
7877
|
-
groups: laidOut
|
|
7895
|
+
groups: laidOut,
|
|
7896
|
+
bands: 1
|
|
7897
|
+
};
|
|
7898
|
+
};
|
|
7899
|
+
/**
|
|
7900
|
+
* Wraps the groups onto bands of equal group count, each band starting back at
|
|
7901
|
+
* the first data line so the groups line up in slots down the bands.
|
|
7902
|
+
*
|
|
7903
|
+
* @param layout - The unwrapped layout from `resolveColumnGroups`.
|
|
7904
|
+
* @param bands - Bands to aim for; the groups split as evenly as whole bands allow.
|
|
7905
|
+
* @return The wrapped layout, or null when there is nothing to wrap: one band, one group, or a column outside every group.
|
|
7906
|
+
*/
|
|
7907
|
+
const wrapColumnGroups = (layout, bands) => {
|
|
7908
|
+
const { columns, groups } = layout;
|
|
7909
|
+
if (bands < 2 || groups.length < 2 || columns.some((column) => column.group === void 0)) return null;
|
|
7910
|
+
const perBand = Math.ceil(groups.length / bands);
|
|
7911
|
+
const slotSpans = Array(perBand).fill(0);
|
|
7912
|
+
groups.forEach((group, index) => {
|
|
7913
|
+
const slot = index % perBand;
|
|
7914
|
+
slotSpans[slot] = Math.max(slotSpans[slot], group.span);
|
|
7915
|
+
});
|
|
7916
|
+
const slotLines = [];
|
|
7917
|
+
let line = columns[0].line;
|
|
7918
|
+
slotSpans.forEach((span, slot) => {
|
|
7919
|
+
if (slot > 0) line += 1;
|
|
7920
|
+
slotLines.push(line);
|
|
7921
|
+
line += span;
|
|
7922
|
+
});
|
|
7923
|
+
const wrappedGroups = groups.map((group, index) => ({
|
|
7924
|
+
...group,
|
|
7925
|
+
line: slotLines[index % perBand],
|
|
7926
|
+
band: Math.floor(index / perBand)
|
|
7927
|
+
}));
|
|
7928
|
+
return {
|
|
7929
|
+
columns: columns.map((column) => {
|
|
7930
|
+
const group = column.group;
|
|
7931
|
+
const offset = column.line - groups[group].line;
|
|
7932
|
+
return {
|
|
7933
|
+
...column,
|
|
7934
|
+
line: wrappedGroups[group].line + offset,
|
|
7935
|
+
band: wrappedGroups[group].band,
|
|
7936
|
+
gapBefore: offset === 0 && group % perBand > 0
|
|
7937
|
+
};
|
|
7938
|
+
}),
|
|
7939
|
+
groups: wrappedGroups,
|
|
7940
|
+
bands: Math.ceil(groups.length / perBand),
|
|
7941
|
+
slotSpans
|
|
7942
|
+
};
|
|
7943
|
+
};
|
|
7944
|
+
//#endregion
|
|
7945
|
+
//#region src/charts/heatmap-chart/private/fit-compact-cells.ts
|
|
7946
|
+
/**
|
|
7947
|
+
* Largest whole-pixel square cell, and the band count giving it, for a compact grid in a box.
|
|
7948
|
+
*
|
|
7949
|
+
* @param input - The box, the grid's layout, and its fixed gaps and label sizes.
|
|
7950
|
+
* @return The fit; one band at `minCellSize` when no band count reaches it.
|
|
7951
|
+
*/
|
|
7952
|
+
const fitCompactCells = (input) => {
|
|
7953
|
+
const { width, height, layout, rows, cellGap, groupGap, minCellSize } = input;
|
|
7954
|
+
const columns = layout.columns.length;
|
|
7955
|
+
if (columns === 0 || rows === 0) return {
|
|
7956
|
+
bands: 1,
|
|
7957
|
+
cellSize: minCellSize
|
|
7958
|
+
};
|
|
7959
|
+
const maxBands = Math.max(1, layout.groups.length);
|
|
7960
|
+
const labelHeights = (input.columnLabelHeight ?? 0) + (input.groupLabelHeight ?? 0);
|
|
7961
|
+
const bandTracks = (input.columnLabelHeight === null ? 0 : 1) + rows + (input.groupLabelHeight === null ? 0 : 1);
|
|
7962
|
+
let best = null;
|
|
7963
|
+
for (let target = 1; target <= maxBands; target++) {
|
|
7964
|
+
const wrapped = target > 1 ? wrapColumnGroups(layout, target) : null;
|
|
7965
|
+
const { bands } = wrapped ?? layout;
|
|
7966
|
+
const cellColumns = wrapped ? wrapped.slotSpans.reduce((sum, span) => sum + span, 0) : columns;
|
|
7967
|
+
const gapTracks = wrapped ? wrapped.slotSpans.length - 1 : layout.columns.filter((column) => column.gapBefore).length;
|
|
7968
|
+
const columnTracks = 1 + cellColumns + gapTracks;
|
|
7969
|
+
const byWidth = (width - input.rowLabelWidth - gapTracks * groupGap - (columnTracks - 1) * cellGap) / cellColumns;
|
|
7970
|
+
const rowTracks = bands * bandTracks + (bands - 1);
|
|
7971
|
+
const byHeight = (height - (bands * labelHeights + (bands - 1) * groupGap + (rowTracks - 1) * cellGap)) / (bands * rows);
|
|
7972
|
+
const cellSize = Math.floor(Math.min(byWidth, byHeight));
|
|
7973
|
+
if (cellSize >= minCellSize && (!best || cellSize > best.cellSize)) best = {
|
|
7974
|
+
bands,
|
|
7975
|
+
cellSize
|
|
7976
|
+
};
|
|
7977
|
+
}
|
|
7978
|
+
return best ?? {
|
|
7979
|
+
bands: 1,
|
|
7980
|
+
cellSize: minCellSize
|
|
7878
7981
|
};
|
|
7879
7982
|
};
|
|
7880
7983
|
//#endregion
|
|
@@ -8018,12 +8121,26 @@ const CELL_VALUE_MODIFIER = {
|
|
|
8018
8121
|
};
|
|
8019
8122
|
const NO_ROW_LABELS = [];
|
|
8020
8123
|
const TOOLTIP_BOX_STYLE = { zIndex: 3 };
|
|
8124
|
+
const largest = (root, selector, size) => Math.max(0, ...Array.from(root.querySelectorAll(selector), (el) => el[size]));
|
|
8125
|
+
const gridBox = (chart, grid) => {
|
|
8126
|
+
let height = chart.clientHeight;
|
|
8127
|
+
const rowGap = parseFloat(getComputedStyle(chart).rowGap) || 0;
|
|
8128
|
+
Array.from(chart.children).forEach((child) => {
|
|
8129
|
+
const { display, position } = getComputedStyle(child);
|
|
8130
|
+
if (child === grid || display === "none" || position === "absolute" || position === "fixed") return;
|
|
8131
|
+
height -= child.offsetHeight + rowGap;
|
|
8132
|
+
});
|
|
8133
|
+
return {
|
|
8134
|
+
width: chart.clientWidth,
|
|
8135
|
+
height
|
|
8136
|
+
};
|
|
8137
|
+
};
|
|
8021
8138
|
const cellName = (info) => info.cellLabel || [
|
|
8022
8139
|
info.groupLabel,
|
|
8023
8140
|
info.columnLabel,
|
|
8024
8141
|
info.rowLabel
|
|
8025
8142
|
].filter(Boolean).join(" ");
|
|
8026
|
-
const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, height = 0, className, compact = false, showValues, maxCellWidth, maxCellHeight, minCellWidth, minCellHeight, rowLabels = NO_ROW_LABELS, columnGroups, keyboardNavigation = "grid", ariaLabel, primaryColor, gap = "md", withTooltips = false, renderTooltip, tooltipStyle, children }) => {
|
|
8143
|
+
const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, height = 0, className, compact = false, fitCells = false, showValues, maxCellWidth, maxCellHeight, minCellWidth, minCellHeight, rowLabels = NO_ROW_LABELS, columnGroups, keyboardNavigation = "grid", ariaLabel, primaryColor, gap = "md", withTooltips = false, renderTooltip, tooltipStyle, children }) => {
|
|
8027
8144
|
const chartId = useChartId(providedChartId);
|
|
8028
8145
|
const tooltipBoxStyle = tooltipStyle ? {
|
|
8029
8146
|
...TOOLTIP_BOX_STYLE,
|
|
@@ -8037,8 +8154,9 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8037
8154
|
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, showTooltip, hideTooltip } = useTooltip();
|
|
8038
8155
|
const standaloneScopeClass = useStandaloneScopeClass();
|
|
8039
8156
|
const containerRef = useRef(null);
|
|
8157
|
+
const chartRef = useRef(null);
|
|
8040
8158
|
const [labelRoles, setLabelRoles] = useState(null);
|
|
8041
|
-
const getTooltipOrigin = useCallback(() =>
|
|
8159
|
+
const getTooltipOrigin = useCallback(() => chartRef.current?.getBoundingClientRect() ?? null, []);
|
|
8042
8160
|
const { color: primaryColorHex } = getElementStyles({
|
|
8043
8161
|
index: 0,
|
|
8044
8162
|
overrideColor: primaryColor
|
|
@@ -8080,6 +8198,49 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8080
8198
|
const groupLayout = useMemo(() => resolveColumnGroups(columnGroups, columns, 2), [columnGroups, columns]);
|
|
8081
8199
|
const { compactCellGap, compactCellSize, groupGap } = heatmapChartSettings;
|
|
8082
8200
|
const drawValues = showValues ?? !compact;
|
|
8201
|
+
const hasColumnLabels = data.some((column) => Boolean(column.label));
|
|
8202
|
+
const hasGroups = groupLayout.groups.length > 0;
|
|
8203
|
+
const [fit, setFit] = useState(null);
|
|
8204
|
+
const hasSummary = data.some((column) => column.summary);
|
|
8205
|
+
const fitting = compact && fitCells && !hasSummary;
|
|
8206
|
+
if (fitCells && !fitting) warnOnce("heatmap:fitCells", "fitCells applies only in compact mode without summary columns, so the cells keep their size.");
|
|
8207
|
+
useIsomorphicLayoutEffect(() => {
|
|
8208
|
+
const chart = chartRef.current;
|
|
8209
|
+
const grid = containerRef.current;
|
|
8210
|
+
if (!fitting || !chart || !grid) {
|
|
8211
|
+
setFit(null);
|
|
8212
|
+
return;
|
|
8213
|
+
}
|
|
8214
|
+
const measure = () => {
|
|
8215
|
+
const next = fitCompactCells({
|
|
8216
|
+
...gridBox(chart, grid),
|
|
8217
|
+
layout: groupLayout,
|
|
8218
|
+
rows,
|
|
8219
|
+
cellGap: compactCellGap,
|
|
8220
|
+
groupGap,
|
|
8221
|
+
rowLabelWidth: largest(grid, `.${heatmap_chart_module_default["heatmap-chart__row-label"]}`, "offsetWidth"),
|
|
8222
|
+
columnLabelHeight: hasColumnLabels ? largest(grid, `.${heatmap_chart_module_default["heatmap-chart__col-label"]}`, "offsetHeight") : null,
|
|
8223
|
+
groupLabelHeight: hasGroups ? largest(grid, `.${heatmap_chart_module_default["heatmap-chart__group-label"]}`, "offsetHeight") : null,
|
|
8224
|
+
minCellSize: compactCellSize
|
|
8225
|
+
});
|
|
8226
|
+
setFit((previous) => (0, import_fast_deep_equal.default)(previous, next) ? previous : next);
|
|
8227
|
+
};
|
|
8228
|
+
measure();
|
|
8229
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
8230
|
+
const observer = new ResizeObserver(() => flushSync(measure));
|
|
8231
|
+
observer.observe(chart);
|
|
8232
|
+
return () => observer.disconnect();
|
|
8233
|
+
}, [
|
|
8234
|
+
fitting,
|
|
8235
|
+
groupLayout,
|
|
8236
|
+
rows,
|
|
8237
|
+
hasColumnLabels,
|
|
8238
|
+
hasGroups,
|
|
8239
|
+
compactCellGap,
|
|
8240
|
+
compactCellSize,
|
|
8241
|
+
groupGap
|
|
8242
|
+
]);
|
|
8243
|
+
const wrapped = useMemo(() => fit ? wrapColumnGroups(groupLayout, fit.bands) : null, [fit, groupLayout]);
|
|
8083
8244
|
const buildTooltipData = useCallback((columnIndex, rowIndex) => {
|
|
8084
8245
|
const cell = data[columnIndex]?.data[rowIndex];
|
|
8085
8246
|
const group = groupLayout.columns[columnIndex]?.group;
|
|
@@ -8219,21 +8380,25 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8219
8380
|
});
|
|
8220
8381
|
const columnTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellWidth ?? 0}px, ${maxCellWidth ? `${maxCellWidth}px` : "1fr"})`;
|
|
8221
8382
|
const rowTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellHeight ?? 0}px, ${maxCellHeight ? `${maxCellHeight}px` : "1fr"})`;
|
|
8222
|
-
const
|
|
8223
|
-
const
|
|
8224
|
-
const
|
|
8225
|
-
const
|
|
8383
|
+
const placed = wrapped ?? groupLayout;
|
|
8384
|
+
const columnLine = (columnIndex) => placed.columns[columnIndex].line;
|
|
8385
|
+
const bandOf = (columnIndex) => placed.columns[columnIndex].band;
|
|
8386
|
+
const { bands } = placed;
|
|
8387
|
+
const bandRowCount = (hasColumnLabels ? 1 : 0) + rows + (hasGroups ? 1 : 0) + 1;
|
|
8388
|
+
const labelRowOf = (band) => 1 + band * bandRowCount;
|
|
8389
|
+
const dataRowOf = (band, rowIndex) => labelRowOf(band) + (hasColumnLabels ? 1 : 0) + rowIndex;
|
|
8226
8390
|
const dataTrack = (column) => column.summary ? "minmax(auto, max-content)" : columnTrack;
|
|
8227
8391
|
const gapTrack = compact ? `minmax(${groupGap}px, 1fr)` : `${groupGap}px`;
|
|
8228
|
-
const columnTracks = data.map((column, columnIndex) => groupLayout.columns[columnIndex].gapBefore ? `${gapTrack} ${dataTrack(column)}` : dataTrack(column)).join(" ");
|
|
8392
|
+
const columnTracks = wrapped ? wrapped.slotSpans.map((span, slot) => [...slot > 0 ? [gapTrack] : [], ...Array(span).fill(columnTrack)].join(" ")).join(" ") : data.map((column, columnIndex) => groupLayout.columns[columnIndex].gapBefore ? `${gapTrack} ${dataTrack(column)}` : dataTrack(column)).join(" ");
|
|
8393
|
+
const bandTracks = `${hasColumnLabels ? "auto " : ""}repeat(${rows}, ${rowTrack})${hasGroups ? " auto" : ""}`;
|
|
8229
8394
|
const gridStyle = {
|
|
8230
8395
|
...fillVars,
|
|
8231
8396
|
gridTemplateColumns: `auto ${columnTracks}`,
|
|
8232
|
-
gridTemplateRows:
|
|
8397
|
+
gridTemplateRows: Array(bands).fill(bandTracks).join(` ${groupGap}px `)
|
|
8233
8398
|
};
|
|
8234
8399
|
if (compact) {
|
|
8235
8400
|
gridStyle["--a8c-charts-dimension-heatmap-cell-gap"] = `${compactCellGap}px`;
|
|
8236
|
-
gridStyle["--a8c-charts-dimension-heatmap-cell-size"] = `${compactCellSize}px`;
|
|
8401
|
+
gridStyle["--a8c-charts-dimension-heatmap-cell-size"] = `${fit?.cellSize ?? compactCellSize}px`;
|
|
8237
8402
|
}
|
|
8238
8403
|
const summaryGaps = (columnIndex) => {
|
|
8239
8404
|
if (!data[columnIndex]?.summary) return {};
|
|
@@ -8253,6 +8418,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8253
8418
|
legendChildren: [],
|
|
8254
8419
|
trailingContent: nonLegendChildren,
|
|
8255
8420
|
gap,
|
|
8421
|
+
rootRef: chartRef,
|
|
8256
8422
|
className: clsx("heatmap-chart", heatmap_chart_module_default["heatmap-chart"], className, { [heatmap_chart_module_default["heatmap-chart--height-capped"]]: heightCapped }),
|
|
8257
8423
|
style: {
|
|
8258
8424
|
width: width || void 0,
|
|
@@ -8282,11 +8448,11 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8282
8448
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8283
8449
|
children: [/* @__PURE__ */ jsx("span", { style: {
|
|
8284
8450
|
gridColumn: 1,
|
|
8285
|
-
gridRow:
|
|
8451
|
+
gridRow: labelRowOf(0)
|
|
8286
8452
|
} }), data.map((column, columnIndex) => /* @__PURE__ */ jsx("span", {
|
|
8287
8453
|
style: {
|
|
8288
8454
|
gridColumn: columnLine(columnIndex),
|
|
8289
|
-
gridRow:
|
|
8455
|
+
gridRow: labelRowOf(bandOf(columnIndex))
|
|
8290
8456
|
},
|
|
8291
8457
|
className: clsx(heatmap_chart_module_default["heatmap-chart__col-label"], {
|
|
8292
8458
|
[heatmap_chart_module_default["heatmap-chart__col-label--summary"]]: column.summary,
|
|
@@ -8297,24 +8463,23 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8297
8463
|
}),
|
|
8298
8464
|
Array.from({ length: rows }).map((_row, rowIndex) => {
|
|
8299
8465
|
const labelVisible = !compact || rowIndex % 2 === 0;
|
|
8300
|
-
const gridRow = firstDataRow + rowIndex;
|
|
8301
8466
|
return /* @__PURE__ */ jsxs("div", {
|
|
8302
8467
|
role: "row",
|
|
8303
8468
|
"aria-rowindex": rowIndex + 1,
|
|
8304
8469
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8305
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
8470
|
+
children: [Array.from({ length: bands }).map((_band, band) => /* @__PURE__ */ jsx("span", {
|
|
8306
8471
|
"aria-hidden": "true",
|
|
8307
8472
|
className: heatmap_chart_module_default["heatmap-chart__row-label"],
|
|
8308
8473
|
style: {
|
|
8309
8474
|
gridColumn: 1,
|
|
8310
|
-
gridRow
|
|
8475
|
+
gridRow: dataRowOf(band, rowIndex)
|
|
8311
8476
|
},
|
|
8312
8477
|
children: labelVisible ? rowLabels[rowIndex] ?? "" : ""
|
|
8313
|
-
}), data.map((column, columnIndex) => {
|
|
8478
|
+
}, `row-label-${band}`)), data.map((column, columnIndex) => {
|
|
8314
8479
|
const cell = column.data[rowIndex];
|
|
8315
8480
|
const placement = {
|
|
8316
8481
|
gridColumn: columnLine(columnIndex),
|
|
8317
|
-
gridRow
|
|
8482
|
+
gridRow: dataRowOf(bandOf(columnIndex), rowIndex)
|
|
8318
8483
|
};
|
|
8319
8484
|
if (cell?.hidden) return /* @__PURE__ */ jsx("div", {
|
|
8320
8485
|
"aria-hidden": "true",
|
|
@@ -8364,11 +8529,11 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8364
8529
|
role: "row",
|
|
8365
8530
|
"aria-hidden": "true",
|
|
8366
8531
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8367
|
-
children:
|
|
8532
|
+
children: placed.groups.map((group, groupIndex) => /* @__PURE__ */ jsx("span", {
|
|
8368
8533
|
className: heatmap_chart_module_default["heatmap-chart__group-label"],
|
|
8369
8534
|
style: {
|
|
8370
8535
|
gridColumn: `${group.line} / span ${group.span}`,
|
|
8371
|
-
gridRow:
|
|
8536
|
+
gridRow: dataRowOf(group.band, rows)
|
|
8372
8537
|
},
|
|
8373
8538
|
children: group.label
|
|
8374
8539
|
}, `group-${groupIndex}`))
|
|
@@ -11238,6 +11403,7 @@ var leaderboard_chart_module_default = {
|
|
|
11238
11403
|
"interactiveRow": "a8ccharts-GovfoW-interactiveRow",
|
|
11239
11404
|
"is-overlay": "a8ccharts-GovfoW-is-overlay",
|
|
11240
11405
|
"label": "a8ccharts-GovfoW-label",
|
|
11406
|
+
"layeredRow": "a8ccharts-GovfoW-layeredRow",
|
|
11241
11407
|
"leaderboardChart": "a8ccharts-GovfoW-leaderboardChart",
|
|
11242
11408
|
"leaderboardChart__content": "a8ccharts-GovfoW-leaderboardChart__content",
|
|
11243
11409
|
"leaderboardChart__content--fit": "a8ccharts-GovfoW-leaderboardChart__content--fit",
|
|
@@ -11246,6 +11412,7 @@ var leaderboard_chart_module_default = {
|
|
|
11246
11412
|
"overlap": "a8ccharts-GovfoW-overlap",
|
|
11247
11413
|
"overlayLabel": "a8ccharts-GovfoW-overlayLabel",
|
|
11248
11414
|
"row": "a8ccharts-GovfoW-row",
|
|
11415
|
+
"rowButton": "a8ccharts-GovfoW-rowButton",
|
|
11249
11416
|
"stretch": "a8ccharts-GovfoW-stretch",
|
|
11250
11417
|
"valueContainer": "a8ccharts-GovfoW-valueContainer"
|
|
11251
11418
|
};
|
|
@@ -11296,6 +11463,16 @@ const defaultDeltaFormatter = (value) => {
|
|
|
11296
11463
|
const getBarWidth = (share) => `calc(${share}% - var(--a8c-charts-dimension-leaderboard-bar-hover-inset, 0px) * ${share} / 100)`;
|
|
11297
11464
|
const hasPreviousValue = (entry) => entry.previousValue != null && entry.previousShare != null;
|
|
11298
11465
|
const hasDeltaValue = (entry) => hasPreviousValue(entry) && entry.delta != null;
|
|
11466
|
+
/**
|
|
11467
|
+
* A layered row's cell that takes pointer events of its own (a value tooltip)
|
|
11468
|
+
* sits above the row button; pass its clicks on so they still drill down.
|
|
11469
|
+
*
|
|
11470
|
+
* @param event - The click on the row.
|
|
11471
|
+
*/
|
|
11472
|
+
function forwardCellClickToRowButton(event) {
|
|
11473
|
+
if (event.target.closest("a, button")) return;
|
|
11474
|
+
event.currentTarget.querySelector(":scope > button")?.click();
|
|
11475
|
+
}
|
|
11299
11476
|
const BarLabel = ({ label }) => /* @__PURE__ */ jsx(Fragment$1, { children: typeof label === "string" ? /* @__PURE__ */ jsx(Text$1, {
|
|
11300
11477
|
className: leaderboard_chart_module_default.label,
|
|
11301
11478
|
children: label
|
|
@@ -11528,6 +11705,26 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
|
|
|
11528
11705
|
})
|
|
11529
11706
|
]
|
|
11530
11707
|
})] });
|
|
11708
|
+
if (entry.onClick && entry.hasInteractiveLabel) return /* @__PURE__ */ jsxs("div", {
|
|
11709
|
+
"data-row-index": rowIndex,
|
|
11710
|
+
style: rowStyle,
|
|
11711
|
+
className: clsx(leaderboard_chart_module_default.row, leaderboard_chart_module_default.interactiveRow, leaderboard_chart_module_default.layeredRow),
|
|
11712
|
+
onClick: forwardCellClickToRowButton,
|
|
11713
|
+
children: [
|
|
11714
|
+
rowCells,
|
|
11715
|
+
/* @__PURE__ */ jsx("button", {
|
|
11716
|
+
type: "button",
|
|
11717
|
+
className: leaderboard_chart_module_default.rowButton,
|
|
11718
|
+
onClick: entry.onClick,
|
|
11719
|
+
"aria-label": entry.ariaLabel
|
|
11720
|
+
}),
|
|
11721
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
11722
|
+
className: leaderboard_chart_module_default.chevron,
|
|
11723
|
+
icon: chevronRight,
|
|
11724
|
+
size: 24
|
|
11725
|
+
})
|
|
11726
|
+
]
|
|
11727
|
+
}, entry.id);
|
|
11531
11728
|
if (entry.onClick) return /* @__PURE__ */ jsxs("button", {
|
|
11532
11729
|
type: "button",
|
|
11533
11730
|
"data-row-index": rowIndex,
|
|
@@ -11561,6 +11758,210 @@ LeaderboardChartWithProvider.displayName = "LeaderboardChart";
|
|
|
11561
11758
|
const LeaderboardChart = attachSubComponents(LeaderboardChartWithProvider, { Legend });
|
|
11562
11759
|
const LeaderboardChartResponsive = attachSubComponents(withResponsive(LeaderboardChartWithProvider), { Legend });
|
|
11563
11760
|
//#endregion
|
|
11761
|
+
//#region src/charts/private/pie-keyboard-navigation/order-arcs-for-navigation.ts
|
|
11762
|
+
/**
|
|
11763
|
+
* Orders arcs the way they appear: clockwise from 12 o'clock, which for a semi-circle is left to right.
|
|
11764
|
+
*
|
|
11765
|
+
* @param arcs - Arcs from visx's `pie` factory, in data order.
|
|
11766
|
+
* @return A copy of `arcs` sorted by angular midpoint.
|
|
11767
|
+
*/
|
|
11768
|
+
const orderArcsForNavigation = (arcs) => [...arcs].sort((a, b) => a.startAngle + a.endAngle - (b.startAngle + b.endAngle));
|
|
11769
|
+
//#endregion
|
|
11770
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-selection-announcement.tsx
|
|
11771
|
+
const PieSelectionAnnouncement = ({ data }) => /* @__PURE__ */ jsx(VisuallyHidden, {
|
|
11772
|
+
role: "status",
|
|
11773
|
+
"aria-atomic": "true",
|
|
11774
|
+
children: data && /* @__PURE__ */ jsx(LabelValueContent, { data })
|
|
11775
|
+
});
|
|
11776
|
+
//#endregion
|
|
11777
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-tooltip.tsx
|
|
11778
|
+
const PieTooltip = ({ top, left, selectedIndex, tooltipRef, children }) => {
|
|
11779
|
+
const standaloneScopeClass = useStandaloneScopeClass();
|
|
11780
|
+
return /* @__PURE__ */ jsx(BoundedTooltip, {
|
|
11781
|
+
top,
|
|
11782
|
+
left,
|
|
11783
|
+
children: selectedIndex === void 0 ? /* @__PURE__ */ jsx("div", {
|
|
11784
|
+
className: standaloneScopeClass,
|
|
11785
|
+
role: "tooltip",
|
|
11786
|
+
children
|
|
11787
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
11788
|
+
ref: tooltipRef,
|
|
11789
|
+
tabIndex: -1,
|
|
11790
|
+
role: "tooltip",
|
|
11791
|
+
"aria-atomic": "true",
|
|
11792
|
+
className: standaloneScopeClass,
|
|
11793
|
+
children
|
|
11794
|
+
}, `chart-tooltip-${selectedIndex}`)
|
|
11795
|
+
});
|
|
11796
|
+
};
|
|
11797
|
+
//#endregion
|
|
11798
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-selection-output.tsx
|
|
11799
|
+
/**
|
|
11800
|
+
* Reports the selected segment: a focused tooltip for a keyboard selection, a pointer tooltip on hover, or a screen reader announcement without tooltips.
|
|
11801
|
+
*
|
|
11802
|
+
* @param {PieSelectionOutputProps} props - Component props
|
|
11803
|
+
* @return {JSX.Element} The announcement region and the tooltip, if any
|
|
11804
|
+
*/
|
|
11805
|
+
const PieSelectionOutput = ({ withTooltips, selectedIndex, selectedData, keyboardTooltipAnchor, pointerTooltip, chartRef, svgRef, tooltipRef, renderTooltip }) => {
|
|
11806
|
+
const [svgOffset, setSvgOffset] = useState({
|
|
11807
|
+
top: 0,
|
|
11808
|
+
left: 0
|
|
11809
|
+
});
|
|
11810
|
+
const showKeyboardTooltip = withTooltips && selectedData && keyboardTooltipAnchor;
|
|
11811
|
+
useLayoutEffect(() => {
|
|
11812
|
+
const chartBounds = chartRef.current?.getBoundingClientRect();
|
|
11813
|
+
const svgBounds = svgRef.current?.getBoundingClientRect();
|
|
11814
|
+
if (!showKeyboardTooltip || !chartBounds || !svgBounds) return;
|
|
11815
|
+
const top = svgBounds.top - chartBounds.top;
|
|
11816
|
+
const left = svgBounds.left - chartBounds.left;
|
|
11817
|
+
setSvgOffset((current) => current.top === top && current.left === left ? current : {
|
|
11818
|
+
top,
|
|
11819
|
+
left
|
|
11820
|
+
});
|
|
11821
|
+
});
|
|
11822
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
11823
|
+
/* @__PURE__ */ jsx(PieSelectionAnnouncement, { data: withTooltips ? void 0 : selectedData }),
|
|
11824
|
+
showKeyboardTooltip && /* @__PURE__ */ jsx(PieTooltip, {
|
|
11825
|
+
top: svgOffset.top + keyboardTooltipAnchor.top,
|
|
11826
|
+
left: svgOffset.left + keyboardTooltipAnchor.left,
|
|
11827
|
+
selectedIndex,
|
|
11828
|
+
tooltipRef,
|
|
11829
|
+
children: renderTooltip({ tooltipData: selectedData })
|
|
11830
|
+
}),
|
|
11831
|
+
withTooltips && !selectedData && pointerTooltip?.data && /* @__PURE__ */ jsx(PieTooltip, {
|
|
11832
|
+
top: pointerTooltip.top,
|
|
11833
|
+
left: pointerTooltip.left,
|
|
11834
|
+
children: renderTooltip({ tooltipData: pointerTooltip.data })
|
|
11835
|
+
})
|
|
11836
|
+
] });
|
|
11837
|
+
};
|
|
11838
|
+
//#endregion
|
|
11839
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-keyboard-navigation.module.scss
|
|
11840
|
+
var pie_keyboard_navigation_module_default = {
|
|
11841
|
+
"selected-ring__contrast": "a8ccharts-V2HDKq-selected-ring__contrast",
|
|
11842
|
+
"selected-ring__focus": "a8ccharts-V2HDKq-selected-ring__focus"
|
|
11843
|
+
};
|
|
11844
|
+
//#endregion
|
|
11845
|
+
//#region src/charts/private/pie-keyboard-navigation/selected-segment-ring.tsx
|
|
11846
|
+
/**
|
|
11847
|
+
* Encodes `value` for an SVG id, losslessly so distinct chart ids never share a clip path.
|
|
11848
|
+
*
|
|
11849
|
+
* @param value - Any string.
|
|
11850
|
+
* @return `value` with each character outside `[A-Za-z0-9-]` written as `_<hex code point>_`.
|
|
11851
|
+
*/
|
|
11852
|
+
const toSvgId = (value) => Array.from(value, (character) => /[A-Za-z0-9-]/.test(character) ? character : `_${character.codePointAt(0)?.toString(16)}_`).join("");
|
|
11853
|
+
/**
|
|
11854
|
+
* Marks the selected segment with a two-tone ring drawn inside its edge, so the SVG edge cannot cut it off.
|
|
11855
|
+
*
|
|
11856
|
+
* @param {SelectedSegmentRingProps} props - Component props
|
|
11857
|
+
* @return {JSX.Element} The ring
|
|
11858
|
+
*/
|
|
11859
|
+
const SelectedSegmentRing = ({ chartId, d }) => {
|
|
11860
|
+
const clipId = `pie-selected-ring-clip-${toSvgId(chartId)}`;
|
|
11861
|
+
const clipPath = `url(#${clipId})`;
|
|
11862
|
+
return /* @__PURE__ */ jsxs("g", {
|
|
11863
|
+
pointerEvents: "none",
|
|
11864
|
+
"aria-hidden": "true",
|
|
11865
|
+
children: [
|
|
11866
|
+
/* @__PURE__ */ jsx("clipPath", {
|
|
11867
|
+
id: clipId,
|
|
11868
|
+
children: /* @__PURE__ */ jsx("path", { d })
|
|
11869
|
+
}),
|
|
11870
|
+
/* @__PURE__ */ jsx("path", {
|
|
11871
|
+
d,
|
|
11872
|
+
clipPath,
|
|
11873
|
+
className: pie_keyboard_navigation_module_default["selected-ring__contrast"]
|
|
11874
|
+
}),
|
|
11875
|
+
/* @__PURE__ */ jsx("path", {
|
|
11876
|
+
d,
|
|
11877
|
+
clipPath,
|
|
11878
|
+
className: pie_keyboard_navigation_module_default["selected-ring__focus"]
|
|
11879
|
+
})
|
|
11880
|
+
]
|
|
11881
|
+
});
|
|
11882
|
+
};
|
|
11883
|
+
//#endregion
|
|
11884
|
+
//#region src/charts/private/pie-keyboard-navigation/use-pie-keyboard-navigation.ts
|
|
11885
|
+
const usePieKeyboardNavigation = ({ navigationArcs, withTooltips, tooltipOffsetX, tooltipOffsetY }) => {
|
|
11886
|
+
const chartRef = useRef(null);
|
|
11887
|
+
const svgRef = useRef(null);
|
|
11888
|
+
const [selectedIndex, setSelectedIndex] = useState(void 0);
|
|
11889
|
+
const [isNavigating, setIsNavigating] = useState(false);
|
|
11890
|
+
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = useTooltip();
|
|
11891
|
+
const { tooltipRef: focusTooltip, onChartFocus, onChartBlur, onChartKeyDown, onChartPointerMove } = useKeyboardNavigation({
|
|
11892
|
+
selectedIndex,
|
|
11893
|
+
setSelectedIndex,
|
|
11894
|
+
isNavigating,
|
|
11895
|
+
setIsNavigating,
|
|
11896
|
+
chartRef,
|
|
11897
|
+
totalPoints: navigationArcs.length,
|
|
11898
|
+
visibleSeriesKey: JSON.stringify(navigationArcs.map((arcDatum) => arcDatum.data.label))
|
|
11899
|
+
});
|
|
11900
|
+
const selectedArc = selectedIndex === void 0 ? void 0 : navigationArcs[selectedIndex];
|
|
11901
|
+
const keyboardTooltip = useRef(null);
|
|
11902
|
+
const tooltipLostFocus = useRef(false);
|
|
11903
|
+
const tooltipRef = useCallback((element) => {
|
|
11904
|
+
if (element) {
|
|
11905
|
+
keyboardTooltip.current = element;
|
|
11906
|
+
focusTooltip(element);
|
|
11907
|
+
} else if (keyboardTooltip.current?.ownerDocument.activeElement === keyboardTooltip.current) tooltipLostFocus.current = true;
|
|
11908
|
+
}, [focusTooltip]);
|
|
11909
|
+
useLayoutEffect(() => {
|
|
11910
|
+
if (!tooltipLostFocus.current) return;
|
|
11911
|
+
tooltipLostFocus.current = false;
|
|
11912
|
+
const { activeElement, body } = chartRef.current?.ownerDocument ?? document;
|
|
11913
|
+
if (activeElement === null || activeElement === body) chartRef.current?.focus();
|
|
11914
|
+
});
|
|
11915
|
+
const getSegmentHandlers = (data, navigationIndex) => ({
|
|
11916
|
+
onMouseMove: (event) => {
|
|
11917
|
+
onChartPointerMove(navigationIndex);
|
|
11918
|
+
if (!withTooltips) return;
|
|
11919
|
+
const bounds = chartRef.current?.getBoundingClientRect();
|
|
11920
|
+
if (!bounds) return;
|
|
11921
|
+
showTooltip({
|
|
11922
|
+
tooltipData: data,
|
|
11923
|
+
tooltipLeft: event.clientX - bounds.left + tooltipOffsetX,
|
|
11924
|
+
tooltipTop: event.clientY - bounds.top + tooltipOffsetY
|
|
11925
|
+
});
|
|
11926
|
+
},
|
|
11927
|
+
onMouseLeave: withTooltips ? hideTooltip : void 0
|
|
11928
|
+
});
|
|
11929
|
+
return {
|
|
11930
|
+
chartRef,
|
|
11931
|
+
svgRef,
|
|
11932
|
+
selectedArc,
|
|
11933
|
+
getSegmentHandlers,
|
|
11934
|
+
getKeyboardTooltipAnchor: useCallback((originX, originY, [x, y]) => withTooltips ? {
|
|
11935
|
+
left: originX + x + tooltipOffsetX,
|
|
11936
|
+
top: originY + y + tooltipOffsetY
|
|
11937
|
+
} : void 0, [
|
|
11938
|
+
withTooltips,
|
|
11939
|
+
tooltipOffsetX,
|
|
11940
|
+
tooltipOffsetY
|
|
11941
|
+
]),
|
|
11942
|
+
selectionOutputProps: {
|
|
11943
|
+
withTooltips,
|
|
11944
|
+
selectedIndex,
|
|
11945
|
+
selectedData: selectedArc?.data,
|
|
11946
|
+
chartRef,
|
|
11947
|
+
svgRef,
|
|
11948
|
+
tooltipRef,
|
|
11949
|
+
pointerTooltip: tooltipOpen ? {
|
|
11950
|
+
data: tooltipData,
|
|
11951
|
+
left: tooltipLeft || 0,
|
|
11952
|
+
top: tooltipTop || 0
|
|
11953
|
+
} : void 0
|
|
11954
|
+
},
|
|
11955
|
+
chartProps: {
|
|
11956
|
+
role: "application",
|
|
11957
|
+
tabIndex: 0,
|
|
11958
|
+
onKeyDown: onChartKeyDown,
|
|
11959
|
+
onFocus: onChartFocus,
|
|
11960
|
+
onBlur: onChartBlur
|
|
11961
|
+
}
|
|
11962
|
+
};
|
|
11963
|
+
};
|
|
11964
|
+
//#endregion
|
|
11564
11965
|
//#region src/charts/private/radial-wipe-animation/radial-wipe-animation.tsx
|
|
11565
11966
|
/**
|
|
11566
11967
|
* Renders a SVG mask that creates a radial wipe animation effect.
|
|
@@ -11656,20 +12057,13 @@ const LABEL_TEXT_MODIFIER = {
|
|
|
11656
12057
|
* @param {PieChartProps} props - Component props
|
|
11657
12058
|
* @return {JSX.Element} The rendered chart component
|
|
11658
12059
|
*/
|
|
11659
|
-
const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false, className, showLegend = false, legend = {}, width: propWidth, height: propHeight, size, animation, thickness = 1, padding = 0, gapScale = 0, cornerScale = 0, showLabels = true, legendValueDisplay = "percentage", children = null, tooltipOffsetX = 0, tooltipOffsetY = -15, renderTooltip = renderDefaultPieTooltip, gap = "md" }) => {
|
|
12060
|
+
const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false, className, showLegend = false, legend = {}, width: propWidth, height: propHeight, size, animation, thickness = 1, padding = 0, gapScale = 0, cornerScale = 0, showLabels = true, legendValueDisplay = "percentage", children = null, tooltipOffsetX = 0, tooltipOffsetY = -15, renderTooltip = renderDefaultPieTooltip, ariaLabel, gap = "md" }) => {
|
|
11660
12061
|
const legendInteractive = legend.interactive ?? false;
|
|
11661
12062
|
const legendPosition = legend.position ?? "bottom";
|
|
11662
12063
|
const providerTheme = useGlobalChartsTheme();
|
|
11663
12064
|
const chartId = useChartId(providedChartId);
|
|
11664
|
-
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = useTooltip();
|
|
11665
|
-
const standaloneScopeClass = useStandaloneScopeClass();
|
|
11666
|
-
const containerRef = useRef(null);
|
|
11667
12065
|
const rootRef = useRef(null);
|
|
11668
12066
|
const [labelRoles, setLabelRoles] = useState(null);
|
|
11669
|
-
const onMouseLeave = useCallback(() => {
|
|
11670
|
-
if (!withTooltips) return;
|
|
11671
|
-
hideTooltip();
|
|
11672
|
-
}, [withTooltips, hideTooltip]);
|
|
11673
12067
|
const { getElementStyles, isSeriesVisible, isColorPaletteResolved } = useGlobalChartsContext();
|
|
11674
12068
|
const { isValid, message } = validateData$1(data);
|
|
11675
12069
|
useLayoutEffect(() => {
|
|
@@ -11713,13 +12107,7 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
11713
12107
|
metadata: chartMetadata
|
|
11714
12108
|
});
|
|
11715
12109
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
11716
|
-
|
|
11717
|
-
className: clsx("pie-chart", pie_chart_module_default["pie-chart"], className),
|
|
11718
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
11719
|
-
className: pie_chart_module_default["error-message"],
|
|
11720
|
-
children: message
|
|
11721
|
-
})
|
|
11722
|
-
});
|
|
12110
|
+
const wipeMask = animation && !prefersReducedMotion ? `url(#radial-wipe-${chartId})` : null;
|
|
11723
12111
|
const padAngle = gapScale * (2 * Math.PI / data.length);
|
|
11724
12112
|
const dataWithIndex = visibleData.map((d) => {
|
|
11725
12113
|
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
@@ -11737,6 +12125,24 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
11737
12125
|
}).color;
|
|
11738
12126
|
}
|
|
11739
12127
|
};
|
|
12128
|
+
const arcs = pie({
|
|
12129
|
+
value: accessors.value,
|
|
12130
|
+
padAngle
|
|
12131
|
+
})(dataWithIndex);
|
|
12132
|
+
const navigationArcs = orderArcsForNavigation(arcs);
|
|
12133
|
+
const { chartRef, svgRef, selectedArc, getSegmentHandlers, getKeyboardTooltipAnchor, selectionOutputProps, chartProps } = usePieKeyboardNavigation({
|
|
12134
|
+
navigationArcs,
|
|
12135
|
+
withTooltips,
|
|
12136
|
+
tooltipOffsetX,
|
|
12137
|
+
tooltipOffsetY
|
|
12138
|
+
});
|
|
12139
|
+
if (!isValid) return /* @__PURE__ */ jsx("div", {
|
|
12140
|
+
className: clsx("pie-chart", pie_chart_module_default["pie-chart"], className),
|
|
12141
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
12142
|
+
className: pie_chart_module_default["error-message"],
|
|
12143
|
+
children: message
|
|
12144
|
+
})
|
|
12145
|
+
});
|
|
11740
12146
|
const legendElement = showLegend && /* @__PURE__ */ jsx(Legend, {
|
|
11741
12147
|
orientation: legend.orientation ?? "horizontal",
|
|
11742
12148
|
position: legendPosition,
|
|
@@ -11775,102 +12181,96 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
11775
12181
|
const innerRadius = thickness === 0 ? 0 : outerRadius * (1 - thickness);
|
|
11776
12182
|
const maxCornerRadius = (outerRadius - innerRadius) / 2;
|
|
11777
12183
|
const cornerRadius = cornerScale ? Math.min(cornerScale * outerRadius, maxCornerRadius) : 0;
|
|
12184
|
+
const path = arc({
|
|
12185
|
+
innerRadius,
|
|
12186
|
+
outerRadius,
|
|
12187
|
+
cornerRadius
|
|
12188
|
+
});
|
|
12189
|
+
const svgLabelSmall = providerTheme.svgLabelSmall;
|
|
12190
|
+
const fontSize = resolveFontSize(svgLabelSmall?.fontSize) ?? 12;
|
|
12191
|
+
const renderLabel = (arcDatum, index) => {
|
|
12192
|
+
if (arcDatum.endAngle - arcDatum.startAngle < .25) return null;
|
|
12193
|
+
const [centroidX, centroidY] = path.centroid(arcDatum);
|
|
12194
|
+
const backgroundWidth = getStringWidth$1(arcDatum.data.label, {
|
|
12195
|
+
fontSize,
|
|
12196
|
+
fontFamily: svgLabelSmall?.fontFamily,
|
|
12197
|
+
fontWeight: svgLabelSmall?.fontWeight
|
|
12198
|
+
}) + 12;
|
|
12199
|
+
const backgroundHeight = fontSize + 12;
|
|
12200
|
+
return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
|
|
12201
|
+
className: pie_chart_module_default["pie-chart__label-plate"],
|
|
12202
|
+
x: centroidX - backgroundWidth / 2,
|
|
12203
|
+
y: centroidY - backgroundHeight / 2,
|
|
12204
|
+
width: backgroundWidth,
|
|
12205
|
+
height: backgroundHeight,
|
|
12206
|
+
rx: 4,
|
|
12207
|
+
ry: 4,
|
|
12208
|
+
pointerEvents: "none"
|
|
12209
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
12210
|
+
className: clsx(pie_chart_module_default["pie-chart__label-text"], LABEL_TEXT_MODIFIER[pickLabelTextColor(accessors.fill(arcDatum.data), labelRoles, "label-inverse")]),
|
|
12211
|
+
x: centroidX,
|
|
12212
|
+
y: centroidY,
|
|
12213
|
+
dy: ".33em",
|
|
12214
|
+
fontSize,
|
|
12215
|
+
textAnchor: "middle",
|
|
12216
|
+
pointerEvents: "none",
|
|
12217
|
+
children: arcDatum.data.label
|
|
12218
|
+
})] }, `label-${index}`);
|
|
12219
|
+
};
|
|
11778
12220
|
return /* @__PURE__ */ jsxs(Center, {
|
|
11779
|
-
ref:
|
|
12221
|
+
ref: chartRef,
|
|
11780
12222
|
className: pie_chart_module_default["pie-chart__plot"],
|
|
12223
|
+
...chartProps,
|
|
12224
|
+
"aria-label": ariaLabel ?? __("Pie chart", "jetpack-charts"),
|
|
11781
12225
|
children: [/* @__PURE__ */ jsxs("svg", {
|
|
12226
|
+
ref: svgRef,
|
|
11782
12227
|
viewBox: `0 0 ${width} ${height}`,
|
|
11783
12228
|
preserveAspectRatio: "xMidYMid meet",
|
|
11784
12229
|
width,
|
|
11785
12230
|
height,
|
|
11786
|
-
children: [
|
|
11787
|
-
|
|
11788
|
-
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
groupProps.onMouseMove = handleMouseMove;
|
|
11830
|
-
groupProps.onMouseLeave = onMouseLeave;
|
|
11831
|
-
}
|
|
11832
|
-
const svgLabelSmall = providerTheme.svgLabelSmall;
|
|
11833
|
-
const fontSize = resolveFontSize(svgLabelSmall?.fontSize) ?? 12;
|
|
11834
|
-
const backgroundWidth = getStringWidth$1(arc.data.label, {
|
|
11835
|
-
fontSize,
|
|
11836
|
-
fontFamily: svgLabelSmall?.fontFamily,
|
|
11837
|
-
fontWeight: svgLabelSmall?.fontWeight
|
|
11838
|
-
}) + 12;
|
|
11839
|
-
const backgroundHeight = fontSize + 12;
|
|
11840
|
-
return /* @__PURE__ */ jsxs("g", {
|
|
11841
|
-
...groupProps,
|
|
11842
|
-
children: [/* @__PURE__ */ jsx("path", { ...pathProps }), showLabels && hasSpaceForLabel && /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
|
|
11843
|
-
className: pie_chart_module_default["pie-chart__label-plate"],
|
|
11844
|
-
x: centroidX - backgroundWidth / 2,
|
|
11845
|
-
y: centroidY - backgroundHeight / 2,
|
|
11846
|
-
width: backgroundWidth,
|
|
11847
|
-
height: backgroundHeight,
|
|
11848
|
-
rx: 4,
|
|
11849
|
-
ry: 4,
|
|
11850
|
-
pointerEvents: "none"
|
|
11851
|
-
}), /* @__PURE__ */ jsx("text", {
|
|
11852
|
-
className: clsx(pie_chart_module_default["pie-chart__label-text"], LABEL_TEXT_MODIFIER[pickLabelTextColor(fill, labelRoles, "label-inverse")]),
|
|
11853
|
-
x: centroidX,
|
|
11854
|
-
y: centroidY,
|
|
11855
|
-
dy: ".33em",
|
|
11856
|
-
fontSize,
|
|
11857
|
-
textAnchor: "middle",
|
|
11858
|
-
pointerEvents: "none",
|
|
11859
|
-
children: arc.data.label
|
|
11860
|
-
})] })]
|
|
11861
|
-
}, `arc-${index}`);
|
|
11862
|
-
});
|
|
11863
|
-
}
|
|
11864
|
-
}), !allSegmentsHidden && svgChildren]
|
|
11865
|
-
})]
|
|
11866
|
-
}), withTooltips && tooltipOpen && tooltipData && /* @__PURE__ */ jsx(BoundedTooltip, {
|
|
11867
|
-
top: tooltipTop || 0,
|
|
11868
|
-
left: tooltipLeft || 0,
|
|
11869
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
11870
|
-
className: standaloneScopeClass,
|
|
11871
|
-
role: "tooltip",
|
|
11872
|
-
children: renderTooltip({ tooltipData })
|
|
11873
|
-
})
|
|
12231
|
+
children: [
|
|
12232
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(RadialWipeAnimation, {
|
|
12233
|
+
id: `radial-wipe-${chartId}`,
|
|
12234
|
+
radius: outerRadius,
|
|
12235
|
+
innerRadius
|
|
12236
|
+
}) }),
|
|
12237
|
+
/* @__PURE__ */ jsx(Group, {
|
|
12238
|
+
top: centerY,
|
|
12239
|
+
left: centerX,
|
|
12240
|
+
mask: wipeMask,
|
|
12241
|
+
children: allSegmentsHidden ? /* @__PURE__ */ jsx(SvgEmptyState, {
|
|
12242
|
+
x: 0,
|
|
12243
|
+
y: 0,
|
|
12244
|
+
width,
|
|
12245
|
+
height,
|
|
12246
|
+
children: getAllHiddenMessage(legendInteractive, "segments")
|
|
12247
|
+
}) : arcs.map((arcDatum, index) => /* @__PURE__ */ jsx("g", {
|
|
12248
|
+
...getSegmentHandlers(arcDatum.data, navigationArcs.indexOf(arcDatum)),
|
|
12249
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
12250
|
+
d: path(arcDatum) || "",
|
|
12251
|
+
fill: accessors.fill(arcDatum.data)
|
|
12252
|
+
})
|
|
12253
|
+
}, `arc-${index}`))
|
|
12254
|
+
}),
|
|
12255
|
+
selectedArc && /* @__PURE__ */ jsx(Group, {
|
|
12256
|
+
top: centerY,
|
|
12257
|
+
left: centerX,
|
|
12258
|
+
children: /* @__PURE__ */ jsx(SelectedSegmentRing, {
|
|
12259
|
+
chartId,
|
|
12260
|
+
d: path(selectedArc) || ""
|
|
12261
|
+
})
|
|
12262
|
+
}),
|
|
12263
|
+
!allSegmentsHidden && /* @__PURE__ */ jsxs(Group, {
|
|
12264
|
+
top: centerY,
|
|
12265
|
+
left: centerX,
|
|
12266
|
+
mask: wipeMask,
|
|
12267
|
+
children: [showLabels && arcs.map(renderLabel), svgChildren]
|
|
12268
|
+
})
|
|
12269
|
+
]
|
|
12270
|
+
}), /* @__PURE__ */ jsx(PieSelectionOutput, {
|
|
12271
|
+
...selectionOutputProps,
|
|
12272
|
+
keyboardTooltipAnchor: selectedArc && getKeyboardTooltipAnchor(centerX, centerY, path.centroid(selectedArc)),
|
|
12273
|
+
renderTooltip
|
|
11874
12274
|
})]
|
|
11875
12275
|
});
|
|
11876
12276
|
}
|
|
@@ -11938,32 +12338,10 @@ const validateData = (data) => {
|
|
|
11938
12338
|
message: ""
|
|
11939
12339
|
};
|
|
11940
12340
|
};
|
|
11941
|
-
const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: propWidth, height: propHeight, thickness = .4, clockwise = true, withTooltips = false, showLegend = false, legend = {}, legendValueDisplay = "percentage", label, animation, note, className, children, tooltipOffsetX = 0, tooltipOffsetY = -15, renderTooltip = renderDefaultPieSemiCircleTooltip, gap = "md" }) => {
|
|
12341
|
+
const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: propWidth, height: propHeight, thickness = .4, clockwise = true, withTooltips = false, showLegend = false, legend = {}, legendValueDisplay = "percentage", label, animation, note, className, children, tooltipOffsetX = 0, tooltipOffsetY = -15, renderTooltip = renderDefaultPieSemiCircleTooltip, ariaLabel, gap = "md" }) => {
|
|
11942
12342
|
const legendInteractive = legend.interactive ?? false;
|
|
11943
12343
|
const legendPosition = legend.position ?? "bottom";
|
|
11944
12344
|
const chartId = useChartId(providedChartId);
|
|
11945
|
-
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = useTooltip();
|
|
11946
|
-
const standaloneScopeClass = useStandaloneScopeClass();
|
|
11947
|
-
const containerRef = useRef(null);
|
|
11948
|
-
const handleMouseMove = useCallback((event, arc) => {
|
|
11949
|
-
const bounds = containerRef.current?.getBoundingClientRect();
|
|
11950
|
-
if (!bounds) return;
|
|
11951
|
-
showTooltip({
|
|
11952
|
-
tooltipData: arc.data,
|
|
11953
|
-
tooltipLeft: event.clientX - bounds.left + tooltipOffsetX,
|
|
11954
|
-
tooltipTop: event.clientY - bounds.top + tooltipOffsetY
|
|
11955
|
-
});
|
|
11956
|
-
}, [
|
|
11957
|
-
showTooltip,
|
|
11958
|
-
tooltipOffsetX,
|
|
11959
|
-
tooltipOffsetY
|
|
11960
|
-
]);
|
|
11961
|
-
const handleMouseLeave = useCallback(() => {
|
|
11962
|
-
hideTooltip();
|
|
11963
|
-
}, [hideTooltip]);
|
|
11964
|
-
const handleArcMouseMove = useCallback((arc) => (event) => {
|
|
11965
|
-
handleMouseMove(event, arc);
|
|
11966
|
-
}, [handleMouseMove]);
|
|
11967
12345
|
const { isValid, message } = validateData(data);
|
|
11968
12346
|
const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
|
|
11969
12347
|
const dataWithPercentages = useDataWithPercentages(data);
|
|
@@ -11997,7 +12375,31 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
11997
12375
|
metadata: chartMetadata
|
|
11998
12376
|
});
|
|
11999
12377
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
12378
|
+
const wipeMask = animation && !prefersReducedMotion ? `url(#radial-wipe-${chartId})` : null;
|
|
12000
12379
|
const effectiveWidth = propWidth || DEFAULT_WIDTH$1;
|
|
12380
|
+
const dataWithIndex = visibleData.map((d) => {
|
|
12381
|
+
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
12382
|
+
return {
|
|
12383
|
+
...d,
|
|
12384
|
+
index: originalIndex >= 0 ? originalIndex : 0
|
|
12385
|
+
};
|
|
12386
|
+
});
|
|
12387
|
+
const startAngle = clockwise ? -Math.PI / 2 : Math.PI / 2;
|
|
12388
|
+
const endAngle = clockwise ? Math.PI / 2 : -Math.PI / 2;
|
|
12389
|
+
const arcs = pie({
|
|
12390
|
+
value: accessors.value,
|
|
12391
|
+
sort: accessors.sort,
|
|
12392
|
+
padAngle: PAD_ANGLE,
|
|
12393
|
+
startAngle,
|
|
12394
|
+
endAngle
|
|
12395
|
+
})(dataWithIndex);
|
|
12396
|
+
const navigationArcs = orderArcsForNavigation(arcs);
|
|
12397
|
+
const { chartRef, svgRef, selectedArc, getSegmentHandlers, getKeyboardTooltipAnchor, selectionOutputProps, chartProps } = usePieKeyboardNavigation({
|
|
12398
|
+
navigationArcs,
|
|
12399
|
+
withTooltips,
|
|
12400
|
+
tooltipOffsetX,
|
|
12401
|
+
tooltipOffsetY
|
|
12402
|
+
});
|
|
12001
12403
|
if (!isValid) {
|
|
12002
12404
|
const errorWidth = propHeight ? Math.min(propWidth || propHeight * 2, propHeight * 2) : effectiveWidth;
|
|
12003
12405
|
const errorHeight = errorWidth / 2;
|
|
@@ -12016,15 +12418,6 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
12016
12418
|
})
|
|
12017
12419
|
});
|
|
12018
12420
|
}
|
|
12019
|
-
const dataWithIndex = visibleData.map((d) => {
|
|
12020
|
-
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
12021
|
-
return {
|
|
12022
|
-
...d,
|
|
12023
|
-
index: originalIndex >= 0 ? originalIndex : 0
|
|
12024
|
-
};
|
|
12025
|
-
});
|
|
12026
|
-
const startAngle = clockwise ? -Math.PI / 2 : Math.PI / 2;
|
|
12027
|
-
const endAngle = clockwise ? Math.PI / 2 : -Math.PI / 2;
|
|
12028
12421
|
const legendElement = showLegend && /* @__PURE__ */ jsx(Legend, {
|
|
12029
12422
|
orientation: legend.orientation ?? "horizontal",
|
|
12030
12423
|
position: legendPosition,
|
|
@@ -12057,52 +12450,60 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
12057
12450
|
const height = width / 2;
|
|
12058
12451
|
const radius = height;
|
|
12059
12452
|
const innerRadius = radius * (1 - thickness);
|
|
12453
|
+
const path = arc({
|
|
12454
|
+
innerRadius,
|
|
12455
|
+
outerRadius: radius,
|
|
12456
|
+
cornerRadius: 3
|
|
12457
|
+
});
|
|
12060
12458
|
return /* @__PURE__ */ jsxs(Center, {
|
|
12061
|
-
ref:
|
|
12459
|
+
ref: chartRef,
|
|
12062
12460
|
className: pie_semi_circle_chart_module_default["pie-semi-circle-chart__plot"],
|
|
12461
|
+
...chartProps,
|
|
12462
|
+
"aria-label": ariaLabel ?? __("Semi-circle chart", "jetpack-charts"),
|
|
12063
12463
|
children: [/* @__PURE__ */ jsxs("svg", {
|
|
12464
|
+
ref: svgRef,
|
|
12064
12465
|
width,
|
|
12065
12466
|
height,
|
|
12066
12467
|
viewBox: `0 0 ${width} ${height}`,
|
|
12067
|
-
children: [
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
/* @__PURE__ */ jsxs(Group, { children: [/* @__PURE__ */ jsx(Text, {
|
|
12468
|
+
children: [
|
|
12469
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(RadialWipeAnimation, {
|
|
12470
|
+
id: `radial-wipe-${chartId}`,
|
|
12471
|
+
radius,
|
|
12472
|
+
innerRadius,
|
|
12473
|
+
startAngle: "-180deg",
|
|
12474
|
+
wipePercentage: 50
|
|
12475
|
+
}) }),
|
|
12476
|
+
/* @__PURE__ */ jsx(Group, {
|
|
12477
|
+
top: height,
|
|
12478
|
+
left: width / 2,
|
|
12479
|
+
mask: wipeMask,
|
|
12480
|
+
children: allSegmentsHidden ? /* @__PURE__ */ jsx(SvgEmptyState, {
|
|
12481
|
+
x: 0,
|
|
12482
|
+
y: -radius / 2,
|
|
12483
|
+
width,
|
|
12484
|
+
height,
|
|
12485
|
+
children: getAllHiddenMessage(legendInteractive, "segments")
|
|
12486
|
+
}) : arcs.map((arcDatum) => /* @__PURE__ */ jsx("g", {
|
|
12487
|
+
...getSegmentHandlers(arcDatum.data, navigationArcs.indexOf(arcDatum)),
|
|
12488
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
12489
|
+
d: path(arcDatum) || "",
|
|
12490
|
+
fill: accessors.fill(arcDatum.data)
|
|
12491
|
+
})
|
|
12492
|
+
}, arcDatum.data.label))
|
|
12493
|
+
}),
|
|
12494
|
+
selectedArc && /* @__PURE__ */ jsx(Group, {
|
|
12495
|
+
top: height,
|
|
12496
|
+
left: width / 2,
|
|
12497
|
+
children: /* @__PURE__ */ jsx(SelectedSegmentRing, {
|
|
12498
|
+
chartId,
|
|
12499
|
+
d: path(selectedArc) || ""
|
|
12500
|
+
})
|
|
12501
|
+
}),
|
|
12502
|
+
!allSegmentsHidden && /* @__PURE__ */ jsxs(Group, {
|
|
12503
|
+
top: height,
|
|
12504
|
+
left: width / 2,
|
|
12505
|
+
mask: wipeMask,
|
|
12506
|
+
children: [/* @__PURE__ */ jsxs(Group, { children: [/* @__PURE__ */ jsx(Text, {
|
|
12106
12507
|
textAnchor: "middle",
|
|
12107
12508
|
verticalAnchor: "start",
|
|
12108
12509
|
y: -40,
|
|
@@ -12114,18 +12515,13 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
12114
12515
|
y: -20,
|
|
12115
12516
|
className: pie_semi_circle_chart_module_default.note,
|
|
12116
12517
|
children: note
|
|
12117
|
-
})] }),
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
12125
|
-
className: standaloneScopeClass,
|
|
12126
|
-
role: "tooltip",
|
|
12127
|
-
children: renderTooltip({ tooltipData })
|
|
12128
|
-
})
|
|
12518
|
+
})] }), svgChildren]
|
|
12519
|
+
})
|
|
12520
|
+
]
|
|
12521
|
+
}), /* @__PURE__ */ jsx(PieSelectionOutput, {
|
|
12522
|
+
...selectionOutputProps,
|
|
12523
|
+
keyboardTooltipAnchor: selectedArc && getKeyboardTooltipAnchor(width / 2, height, path.centroid(selectedArc)),
|
|
12524
|
+
renderTooltip
|
|
12129
12525
|
})]
|
|
12130
12526
|
});
|
|
12131
12527
|
}
|