@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.cjs
CHANGED
|
@@ -3082,7 +3082,7 @@ const XYChartTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocu
|
|
|
3082
3082
|
/** @deprecated Use `XYChartTooltip`. */
|
|
3083
3083
|
const AccessibleTooltip = XYChartTooltip;
|
|
3084
3084
|
const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating, setIsNavigating, chartRef, totalPoints, onActivate, preventTooltipScroll = false, visibleSeriesKey }) => {
|
|
3085
|
-
const getChartRoot = (0, react.useCallback)(() => chartRef.current?.closest("[role=\"
|
|
3085
|
+
const getChartRoot = (0, react.useCallback)(() => chartRef.current?.closest("[role=\"application\"]") ?? chartRef.current, [chartRef]);
|
|
3086
3086
|
const focusWithoutScrollIfNeeded = (0, react.useCallback)((element) => {
|
|
3087
3087
|
if (preventTooltipScroll) element?.focus({ preventScroll: true });
|
|
3088
3088
|
else element?.focus();
|
|
@@ -3297,11 +3297,13 @@ function useChartChildren(children, chartType) {
|
|
|
3297
3297
|
}
|
|
3298
3298
|
const displayName = child.type?.displayName;
|
|
3299
3299
|
if (displayName === `${chartType}.SVG` || displayName === "Chart.SVG") {
|
|
3300
|
-
|
|
3300
|
+
const { children: svgChildren } = child.props ?? {};
|
|
3301
|
+
if (svgChildren) react.Children.forEach(svgChildren, (svgChild) => {
|
|
3301
3302
|
svg.push(svgChild);
|
|
3302
3303
|
});
|
|
3303
3304
|
} else if (displayName === `${chartType}.HTML` || displayName === "Chart.HTML") {
|
|
3304
|
-
|
|
3305
|
+
const { children: htmlChildren } = child.props ?? {};
|
|
3306
|
+
if (htmlChildren) react.Children.forEach(htmlChildren, (htmlChild) => {
|
|
3305
3307
|
html.push(htmlChild);
|
|
3306
3308
|
});
|
|
3307
3309
|
} else if (child.type === _visx_group.Group) svg.push(child);
|
|
@@ -4123,6 +4125,7 @@ var line_chart_module_default = {
|
|
|
4123
4125
|
"line-chart--animated": "a8ccharts-inuQka-line-chart--animated",
|
|
4124
4126
|
"rise": "a8ccharts-inuQka-rise"
|
|
4125
4127
|
};
|
|
4128
|
+
const isReact18 = react.version.startsWith("18.");
|
|
4126
4129
|
const CloseIcon = () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
4127
4130
|
width: "16",
|
|
4128
4131
|
height: "16",
|
|
@@ -4165,7 +4168,7 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
|
|
|
4165
4168
|
className: line_chart_module_default["line-chart__annotation-label"],
|
|
4166
4169
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4167
4170
|
ref: buttonRef,
|
|
4168
|
-
popovertarget: popoverId,
|
|
4171
|
+
...isReact18 ? { popovertarget: popoverId } : { popoverTarget: popoverId },
|
|
4169
4172
|
className: line_chart_module_default["line-chart__annotation-label-trigger-button"],
|
|
4170
4173
|
style: {
|
|
4171
4174
|
width: `44px`,
|
|
@@ -4193,8 +4196,13 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
|
|
|
4193
4196
|
subtitle
|
|
4194
4197
|
})
|
|
4195
4198
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4196
|
-
|
|
4197
|
-
|
|
4199
|
+
...isReact18 ? {
|
|
4200
|
+
popovertarget: popoverId,
|
|
4201
|
+
popovertargetaction: "hide"
|
|
4202
|
+
} : {
|
|
4203
|
+
popoverTarget: popoverId,
|
|
4204
|
+
popoverTargetAction: "hide"
|
|
4205
|
+
},
|
|
4198
4206
|
className: line_chart_module_default["line-chart__annotation-label-popover-close-button"],
|
|
4199
4207
|
"aria-label": (0, _wordpress_i18n.__)("Close", "jetpack-charts"),
|
|
4200
4208
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CloseIcon, {})
|
|
@@ -4716,7 +4724,7 @@ const LineChartScalesRef = ({ chartRef, width, height, margin }) => {
|
|
|
4716
4724
|
]);
|
|
4717
4725
|
return null;
|
|
4718
4726
|
};
|
|
4719
|
-
const LineChartInternal = (0, react.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) => {
|
|
4727
|
+
const LineChartInternal = (0, react.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) => {
|
|
4720
4728
|
const legendInteractive = legend.interactive ?? false;
|
|
4721
4729
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
4722
4730
|
const legendComparisonItem = legend.comparisonItem ?? false;
|
|
@@ -4984,8 +4992,8 @@ const LineChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartI
|
|
|
4984
4992
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
4985
4993
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4986
4994
|
ref: chartRef,
|
|
4987
|
-
role: "
|
|
4988
|
-
"aria-label": (0, _wordpress_i18n.__)("Line chart", "jetpack-charts"),
|
|
4995
|
+
role: "application",
|
|
4996
|
+
"aria-label": ariaLabel ?? (0, _wordpress_i18n.__)("Line chart", "jetpack-charts"),
|
|
4989
4997
|
tabIndex: 0,
|
|
4990
4998
|
onKeyDown: onChartKeyDown,
|
|
4991
4999
|
onFocus: onChartFocus,
|
|
@@ -4993,6 +5001,7 @@ const LineChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartI
|
|
|
4993
5001
|
children: chartHeight > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4994
5002
|
className: xy_plot_module_default["xy-plot"],
|
|
4995
5003
|
children: [zoomable && zoom.domain && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_xychart.XYChart, {
|
|
5004
|
+
accessibilityLabel: "",
|
|
4996
5005
|
theme,
|
|
4997
5006
|
width,
|
|
4998
5007
|
height: chartHeight,
|
|
@@ -5233,7 +5242,7 @@ const HoverGlyphs = ({ visibleSeries, stacked, stackOffset, getElementStyles, st
|
|
|
5233
5242
|
};
|
|
5234
5243
|
//#endregion
|
|
5235
5244
|
//#region src/charts/area-chart/area-chart.tsx
|
|
5236
|
-
const AreaChartInternal = (0, react.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) => {
|
|
5245
|
+
const AreaChartInternal = (0, react.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) => {
|
|
5237
5246
|
const legendInteractive = legend.interactive ?? false;
|
|
5238
5247
|
const legendShape = legend.shape ?? "rect";
|
|
5239
5248
|
const legendPosition = legend.position ?? "bottom";
|
|
@@ -5504,8 +5513,8 @@ const AreaChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartI
|
|
|
5504
5513
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
5505
5514
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5506
5515
|
ref: chartRef,
|
|
5507
|
-
role: "
|
|
5508
|
-
"aria-label": (0, _wordpress_i18n.__)("Area chart", "jetpack-charts"),
|
|
5516
|
+
role: "application",
|
|
5517
|
+
"aria-label": ariaLabel ?? (0, _wordpress_i18n.__)("Area chart", "jetpack-charts"),
|
|
5509
5518
|
tabIndex: 0,
|
|
5510
5519
|
onKeyDown: onChartKeyDown,
|
|
5511
5520
|
onFocus: onChartFocus,
|
|
@@ -5513,6 +5522,7 @@ const AreaChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartI
|
|
|
5513
5522
|
children: chartHeight > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5514
5523
|
className: xy_plot_module_default["xy-plot"],
|
|
5515
5524
|
children: [zoomable && zoom.domain && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_xychart.XYChart, {
|
|
5525
|
+
accessibilityLabel: "",
|
|
5516
5526
|
theme,
|
|
5517
5527
|
width,
|
|
5518
5528
|
height: chartHeight,
|
|
@@ -6365,7 +6375,7 @@ const renderTooltipRow = (label, value) => /* @__PURE__ */ (0, react_jsx_runtime
|
|
|
6365
6375
|
className: bar_chart_module_default["bar-chart__tooltip-row"],
|
|
6366
6376
|
children: (0, _wordpress_i18n.sprintf)((0, _wordpress_i18n.__)("%1$s: %2$s", "jetpack-charts"), label, value)
|
|
6367
6377
|
});
|
|
6368
|
-
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 }) => {
|
|
6378
|
+
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 }) => {
|
|
6369
6379
|
if (!withTooltips && (withBandHighlight || onBandHighlightChange)) warnOnce("bar-chart-band-highlight-without-tooltips", "BarChart: withBandHighlight and onBandHighlightChange require withTooltips.");
|
|
6370
6380
|
const legendInteractive = legend.interactive ?? false;
|
|
6371
6381
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
@@ -6673,9 +6683,9 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6673
6683
|
children: ({ contentHeight }) => {
|
|
6674
6684
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
6675
6685
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6676
|
-
role: "
|
|
6686
|
+
role: "application",
|
|
6677
6687
|
ref: chartRef,
|
|
6678
|
-
"aria-label": (0, _wordpress_i18n.__)("Bar chart", "jetpack-charts"),
|
|
6688
|
+
"aria-label": ariaLabel ?? (0, _wordpress_i18n.__)("Bar chart", "jetpack-charts"),
|
|
6679
6689
|
tabIndex: 0,
|
|
6680
6690
|
onKeyDown: onChartKeyDown,
|
|
6681
6691
|
onFocus: onChartFocus,
|
|
@@ -6683,6 +6693,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6683
6693
|
children: chartHeight > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6684
6694
|
className: xy_plot_module_default["xy-plot"],
|
|
6685
6695
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_xychart.XYChart, {
|
|
6696
|
+
accessibilityLabel: "",
|
|
6686
6697
|
theme,
|
|
6687
6698
|
width,
|
|
6688
6699
|
height: chartHeight,
|
|
@@ -7688,6 +7699,7 @@ var heatmap_chart_module_default = {
|
|
|
7688
7699
|
"heatmap-chart__legend-label": "a8ccharts-O3YMOW-heatmap-chart__legend-label",
|
|
7689
7700
|
"heatmap-chart__legend-scale--bar": "a8ccharts-O3YMOW-heatmap-chart__legend-scale--bar",
|
|
7690
7701
|
"heatmap-chart__legend-swatch": "a8ccharts-O3YMOW-heatmap-chart__legend-swatch",
|
|
7702
|
+
"heatmap-chart__legend-swatch--empty": "a8ccharts-O3YMOW-heatmap-chart__legend-swatch--empty",
|
|
7691
7703
|
"heatmap-chart__row": "a8ccharts-O3YMOW-heatmap-chart__row",
|
|
7692
7704
|
"heatmap-chart__row-label": "a8ccharts-O3YMOW-heatmap-chart__row-label",
|
|
7693
7705
|
"heatmap-chart--height-capped": "a8ccharts-O3YMOW-heatmap-chart--height-capped"
|
|
@@ -7785,8 +7797,9 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7785
7797
|
const context = (0, react.useContext)(HeatmapContext);
|
|
7786
7798
|
const { legend } = useGlobalChartsTheme();
|
|
7787
7799
|
if (!context) return null;
|
|
7788
|
-
const { fillVars } = context;
|
|
7800
|
+
const { extent, fillVars } = context;
|
|
7789
7801
|
const labelStyle = legend.labelStyles;
|
|
7802
|
+
const showsEmptyCell = isEmptyValue(0, extent);
|
|
7790
7803
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_wordpress_ui.Stack, {
|
|
7791
7804
|
direction: "row",
|
|
7792
7805
|
gap: "xs",
|
|
@@ -7798,12 +7811,12 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7798
7811
|
style: labelStyle,
|
|
7799
7812
|
children: lessLabel ?? (0, _wordpress_i18n.__)("Less", "jetpack-charts")
|
|
7800
7813
|
}),
|
|
7801
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7814
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_wordpress_ui.Stack, {
|
|
7802
7815
|
direction: "row",
|
|
7803
7816
|
gap: variant === "bar" ? void 0 : "xs",
|
|
7804
7817
|
"aria-hidden": "true",
|
|
7805
7818
|
className: variant === "bar" ? heatmap_chart_module_default["heatmap-chart__legend-scale--bar"] : void 0,
|
|
7806
|
-
children: Array.from({ length: steps }, (_, index) => {
|
|
7819
|
+
children: [showsEmptyCell && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: (0, clsx.default)(heatmap_chart_module_default["heatmap-chart__legend-swatch"], heatmap_chart_module_default["heatmap-chart__legend-swatch--empty"]) }), Array.from({ length: steps }, (_, index) => {
|
|
7807
7820
|
const intensity = steps <= 1 ? 1 : index / (steps - 1);
|
|
7808
7821
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7809
7822
|
className: heatmap_chart_module_default["heatmap-chart__legend-swatch"],
|
|
@@ -7812,7 +7825,7 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7812
7825
|
"--a8c-charts-heatmap-cell-intensity": intensity
|
|
7813
7826
|
}
|
|
7814
7827
|
}, index);
|
|
7815
|
-
})
|
|
7828
|
+
})]
|
|
7816
7829
|
}),
|
|
7817
7830
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_ui.Text, {
|
|
7818
7831
|
variant: "body-sm",
|
|
@@ -7838,9 +7851,11 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7838
7851
|
const ungrouped = () => ({
|
|
7839
7852
|
columns: Array.from({ length: columnCount }, (_, index) => ({
|
|
7840
7853
|
line: firstLine + index,
|
|
7854
|
+
band: 0,
|
|
7841
7855
|
gapBefore: false
|
|
7842
7856
|
})),
|
|
7843
|
-
groups: []
|
|
7857
|
+
groups: [],
|
|
7858
|
+
bands: 1
|
|
7844
7859
|
});
|
|
7845
7860
|
if (!groups || groups.length === 0 || columnCount === 0) return ungrouped();
|
|
7846
7861
|
const spans = groups.map((group) => group.span);
|
|
@@ -7856,11 +7871,13 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7856
7871
|
if (groupIndex > 0) line += 1;
|
|
7857
7872
|
laidOut.push({
|
|
7858
7873
|
...group,
|
|
7859
|
-
line
|
|
7874
|
+
line,
|
|
7875
|
+
band: 0
|
|
7860
7876
|
});
|
|
7861
7877
|
for (let offset = 0; offset < group.span; offset++) {
|
|
7862
7878
|
columns.push({
|
|
7863
7879
|
line,
|
|
7880
|
+
band: 0,
|
|
7864
7881
|
gapBefore: groupIndex > 0 && offset === 0,
|
|
7865
7882
|
group: groupIndex
|
|
7866
7883
|
});
|
|
@@ -7870,13 +7887,99 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7870
7887
|
while (columns.length < columnCount) {
|
|
7871
7888
|
columns.push({
|
|
7872
7889
|
line,
|
|
7890
|
+
band: 0,
|
|
7873
7891
|
gapBefore: false
|
|
7874
7892
|
});
|
|
7875
7893
|
line += 1;
|
|
7876
7894
|
}
|
|
7877
7895
|
return {
|
|
7878
7896
|
columns,
|
|
7879
|
-
groups: laidOut
|
|
7897
|
+
groups: laidOut,
|
|
7898
|
+
bands: 1
|
|
7899
|
+
};
|
|
7900
|
+
};
|
|
7901
|
+
/**
|
|
7902
|
+
* Wraps the groups onto bands of equal group count, each band starting back at
|
|
7903
|
+
* the first data line so the groups line up in slots down the bands.
|
|
7904
|
+
*
|
|
7905
|
+
* @param layout - The unwrapped layout from `resolveColumnGroups`.
|
|
7906
|
+
* @param bands - Bands to aim for; the groups split as evenly as whole bands allow.
|
|
7907
|
+
* @return The wrapped layout, or null when there is nothing to wrap: one band, one group, or a column outside every group.
|
|
7908
|
+
*/
|
|
7909
|
+
const wrapColumnGroups = (layout, bands) => {
|
|
7910
|
+
const { columns, groups } = layout;
|
|
7911
|
+
if (bands < 2 || groups.length < 2 || columns.some((column) => column.group === void 0)) return null;
|
|
7912
|
+
const perBand = Math.ceil(groups.length / bands);
|
|
7913
|
+
const slotSpans = Array(perBand).fill(0);
|
|
7914
|
+
groups.forEach((group, index) => {
|
|
7915
|
+
const slot = index % perBand;
|
|
7916
|
+
slotSpans[slot] = Math.max(slotSpans[slot], group.span);
|
|
7917
|
+
});
|
|
7918
|
+
const slotLines = [];
|
|
7919
|
+
let line = columns[0].line;
|
|
7920
|
+
slotSpans.forEach((span, slot) => {
|
|
7921
|
+
if (slot > 0) line += 1;
|
|
7922
|
+
slotLines.push(line);
|
|
7923
|
+
line += span;
|
|
7924
|
+
});
|
|
7925
|
+
const wrappedGroups = groups.map((group, index) => ({
|
|
7926
|
+
...group,
|
|
7927
|
+
line: slotLines[index % perBand],
|
|
7928
|
+
band: Math.floor(index / perBand)
|
|
7929
|
+
}));
|
|
7930
|
+
return {
|
|
7931
|
+
columns: columns.map((column) => {
|
|
7932
|
+
const group = column.group;
|
|
7933
|
+
const offset = column.line - groups[group].line;
|
|
7934
|
+
return {
|
|
7935
|
+
...column,
|
|
7936
|
+
line: wrappedGroups[group].line + offset,
|
|
7937
|
+
band: wrappedGroups[group].band,
|
|
7938
|
+
gapBefore: offset === 0 && group % perBand > 0
|
|
7939
|
+
};
|
|
7940
|
+
}),
|
|
7941
|
+
groups: wrappedGroups,
|
|
7942
|
+
bands: Math.ceil(groups.length / perBand),
|
|
7943
|
+
slotSpans
|
|
7944
|
+
};
|
|
7945
|
+
};
|
|
7946
|
+
//#endregion
|
|
7947
|
+
//#region src/charts/heatmap-chart/private/fit-compact-cells.ts
|
|
7948
|
+
/**
|
|
7949
|
+
* Largest whole-pixel square cell, and the band count giving it, for a compact grid in a box.
|
|
7950
|
+
*
|
|
7951
|
+
* @param input - The box, the grid's layout, and its fixed gaps and label sizes.
|
|
7952
|
+
* @return The fit; one band at `minCellSize` when no band count reaches it.
|
|
7953
|
+
*/
|
|
7954
|
+
const fitCompactCells = (input) => {
|
|
7955
|
+
const { width, height, layout, rows, cellGap, groupGap, minCellSize } = input;
|
|
7956
|
+
const columns = layout.columns.length;
|
|
7957
|
+
if (columns === 0 || rows === 0) return {
|
|
7958
|
+
bands: 1,
|
|
7959
|
+
cellSize: minCellSize
|
|
7960
|
+
};
|
|
7961
|
+
const maxBands = Math.max(1, layout.groups.length);
|
|
7962
|
+
const labelHeights = (input.columnLabelHeight ?? 0) + (input.groupLabelHeight ?? 0);
|
|
7963
|
+
const bandTracks = (input.columnLabelHeight === null ? 0 : 1) + rows + (input.groupLabelHeight === null ? 0 : 1);
|
|
7964
|
+
let best = null;
|
|
7965
|
+
for (let target = 1; target <= maxBands; target++) {
|
|
7966
|
+
const wrapped = target > 1 ? wrapColumnGroups(layout, target) : null;
|
|
7967
|
+
const { bands } = wrapped ?? layout;
|
|
7968
|
+
const cellColumns = wrapped ? wrapped.slotSpans.reduce((sum, span) => sum + span, 0) : columns;
|
|
7969
|
+
const gapTracks = wrapped ? wrapped.slotSpans.length - 1 : layout.columns.filter((column) => column.gapBefore).length;
|
|
7970
|
+
const columnTracks = 1 + cellColumns + gapTracks;
|
|
7971
|
+
const byWidth = (width - input.rowLabelWidth - gapTracks * groupGap - (columnTracks - 1) * cellGap) / cellColumns;
|
|
7972
|
+
const rowTracks = bands * bandTracks + (bands - 1);
|
|
7973
|
+
const byHeight = (height - (bands * labelHeights + (bands - 1) * groupGap + (rowTracks - 1) * cellGap)) / (bands * rows);
|
|
7974
|
+
const cellSize = Math.floor(Math.min(byWidth, byHeight));
|
|
7975
|
+
if (cellSize >= minCellSize && (!best || cellSize > best.cellSize)) best = {
|
|
7976
|
+
bands,
|
|
7977
|
+
cellSize
|
|
7978
|
+
};
|
|
7979
|
+
}
|
|
7980
|
+
return best ?? {
|
|
7981
|
+
bands: 1,
|
|
7982
|
+
cellSize: minCellSize
|
|
7880
7983
|
};
|
|
7881
7984
|
};
|
|
7882
7985
|
//#endregion
|
|
@@ -8020,12 +8123,26 @@ const CELL_VALUE_MODIFIER = {
|
|
|
8020
8123
|
};
|
|
8021
8124
|
const NO_ROW_LABELS = [];
|
|
8022
8125
|
const TOOLTIP_BOX_STYLE = { zIndex: 3 };
|
|
8126
|
+
const largest = (root, selector, size) => Math.max(0, ...Array.from(root.querySelectorAll(selector), (el) => el[size]));
|
|
8127
|
+
const gridBox = (chart, grid) => {
|
|
8128
|
+
let height = chart.clientHeight;
|
|
8129
|
+
const rowGap = parseFloat(getComputedStyle(chart).rowGap) || 0;
|
|
8130
|
+
Array.from(chart.children).forEach((child) => {
|
|
8131
|
+
const { display, position } = getComputedStyle(child);
|
|
8132
|
+
if (child === grid || display === "none" || position === "absolute" || position === "fixed") return;
|
|
8133
|
+
height -= child.offsetHeight + rowGap;
|
|
8134
|
+
});
|
|
8135
|
+
return {
|
|
8136
|
+
width: chart.clientWidth,
|
|
8137
|
+
height
|
|
8138
|
+
};
|
|
8139
|
+
};
|
|
8023
8140
|
const cellName = (info) => info.cellLabel || [
|
|
8024
8141
|
info.groupLabel,
|
|
8025
8142
|
info.columnLabel,
|
|
8026
8143
|
info.rowLabel
|
|
8027
8144
|
].filter(Boolean).join(" ");
|
|
8028
|
-
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 }) => {
|
|
8145
|
+
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 }) => {
|
|
8029
8146
|
const chartId = useChartId(providedChartId);
|
|
8030
8147
|
const tooltipBoxStyle = tooltipStyle ? {
|
|
8031
8148
|
...TOOLTIP_BOX_STYLE,
|
|
@@ -8039,8 +8156,9 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8039
8156
|
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, showTooltip, hideTooltip } = (0, _visx_tooltip.useTooltip)();
|
|
8040
8157
|
const standaloneScopeClass = useStandaloneScopeClass();
|
|
8041
8158
|
const containerRef = (0, react.useRef)(null);
|
|
8159
|
+
const chartRef = (0, react.useRef)(null);
|
|
8042
8160
|
const [labelRoles, setLabelRoles] = (0, react.useState)(null);
|
|
8043
|
-
const getTooltipOrigin = (0, react.useCallback)(() =>
|
|
8161
|
+
const getTooltipOrigin = (0, react.useCallback)(() => chartRef.current?.getBoundingClientRect() ?? null, []);
|
|
8044
8162
|
const { color: primaryColorHex } = getElementStyles({
|
|
8045
8163
|
index: 0,
|
|
8046
8164
|
overrideColor: primaryColor
|
|
@@ -8082,6 +8200,49 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8082
8200
|
const groupLayout = (0, react.useMemo)(() => resolveColumnGroups(columnGroups, columns, 2), [columnGroups, columns]);
|
|
8083
8201
|
const { compactCellGap, compactCellSize, groupGap } = heatmapChartSettings;
|
|
8084
8202
|
const drawValues = showValues ?? !compact;
|
|
8203
|
+
const hasColumnLabels = data.some((column) => Boolean(column.label));
|
|
8204
|
+
const hasGroups = groupLayout.groups.length > 0;
|
|
8205
|
+
const [fit, setFit] = (0, react.useState)(null);
|
|
8206
|
+
const hasSummary = data.some((column) => column.summary);
|
|
8207
|
+
const fitting = compact && fitCells && !hasSummary;
|
|
8208
|
+
if (fitCells && !fitting) warnOnce("heatmap:fitCells", "fitCells applies only in compact mode without summary columns, so the cells keep their size.");
|
|
8209
|
+
useIsomorphicLayoutEffect(() => {
|
|
8210
|
+
const chart = chartRef.current;
|
|
8211
|
+
const grid = containerRef.current;
|
|
8212
|
+
if (!fitting || !chart || !grid) {
|
|
8213
|
+
setFit(null);
|
|
8214
|
+
return;
|
|
8215
|
+
}
|
|
8216
|
+
const measure = () => {
|
|
8217
|
+
const next = fitCompactCells({
|
|
8218
|
+
...gridBox(chart, grid),
|
|
8219
|
+
layout: groupLayout,
|
|
8220
|
+
rows,
|
|
8221
|
+
cellGap: compactCellGap,
|
|
8222
|
+
groupGap,
|
|
8223
|
+
rowLabelWidth: largest(grid, `.${heatmap_chart_module_default["heatmap-chart__row-label"]}`, "offsetWidth"),
|
|
8224
|
+
columnLabelHeight: hasColumnLabels ? largest(grid, `.${heatmap_chart_module_default["heatmap-chart__col-label"]}`, "offsetHeight") : null,
|
|
8225
|
+
groupLabelHeight: hasGroups ? largest(grid, `.${heatmap_chart_module_default["heatmap-chart__group-label"]}`, "offsetHeight") : null,
|
|
8226
|
+
minCellSize: compactCellSize
|
|
8227
|
+
});
|
|
8228
|
+
setFit((previous) => (0, import_fast_deep_equal.default)(previous, next) ? previous : next);
|
|
8229
|
+
};
|
|
8230
|
+
measure();
|
|
8231
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
8232
|
+
const observer = new ResizeObserver(() => (0, react_dom.flushSync)(measure));
|
|
8233
|
+
observer.observe(chart);
|
|
8234
|
+
return () => observer.disconnect();
|
|
8235
|
+
}, [
|
|
8236
|
+
fitting,
|
|
8237
|
+
groupLayout,
|
|
8238
|
+
rows,
|
|
8239
|
+
hasColumnLabels,
|
|
8240
|
+
hasGroups,
|
|
8241
|
+
compactCellGap,
|
|
8242
|
+
compactCellSize,
|
|
8243
|
+
groupGap
|
|
8244
|
+
]);
|
|
8245
|
+
const wrapped = (0, react.useMemo)(() => fit ? wrapColumnGroups(groupLayout, fit.bands) : null, [fit, groupLayout]);
|
|
8085
8246
|
const buildTooltipData = (0, react.useCallback)((columnIndex, rowIndex) => {
|
|
8086
8247
|
const cell = data[columnIndex]?.data[rowIndex];
|
|
8087
8248
|
const group = groupLayout.columns[columnIndex]?.group;
|
|
@@ -8221,21 +8382,25 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8221
8382
|
});
|
|
8222
8383
|
const columnTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellWidth ?? 0}px, ${maxCellWidth ? `${maxCellWidth}px` : "1fr"})`;
|
|
8223
8384
|
const rowTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellHeight ?? 0}px, ${maxCellHeight ? `${maxCellHeight}px` : "1fr"})`;
|
|
8224
|
-
const
|
|
8225
|
-
const
|
|
8226
|
-
const
|
|
8227
|
-
const
|
|
8385
|
+
const placed = wrapped ?? groupLayout;
|
|
8386
|
+
const columnLine = (columnIndex) => placed.columns[columnIndex].line;
|
|
8387
|
+
const bandOf = (columnIndex) => placed.columns[columnIndex].band;
|
|
8388
|
+
const { bands } = placed;
|
|
8389
|
+
const bandRowCount = (hasColumnLabels ? 1 : 0) + rows + (hasGroups ? 1 : 0) + 1;
|
|
8390
|
+
const labelRowOf = (band) => 1 + band * bandRowCount;
|
|
8391
|
+
const dataRowOf = (band, rowIndex) => labelRowOf(band) + (hasColumnLabels ? 1 : 0) + rowIndex;
|
|
8228
8392
|
const dataTrack = (column) => column.summary ? "minmax(auto, max-content)" : columnTrack;
|
|
8229
8393
|
const gapTrack = compact ? `minmax(${groupGap}px, 1fr)` : `${groupGap}px`;
|
|
8230
|
-
const columnTracks = data.map((column, columnIndex) => groupLayout.columns[columnIndex].gapBefore ? `${gapTrack} ${dataTrack(column)}` : dataTrack(column)).join(" ");
|
|
8394
|
+
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(" ");
|
|
8395
|
+
const bandTracks = `${hasColumnLabels ? "auto " : ""}repeat(${rows}, ${rowTrack})${hasGroups ? " auto" : ""}`;
|
|
8231
8396
|
const gridStyle = {
|
|
8232
8397
|
...fillVars,
|
|
8233
8398
|
gridTemplateColumns: `auto ${columnTracks}`,
|
|
8234
|
-
gridTemplateRows:
|
|
8399
|
+
gridTemplateRows: Array(bands).fill(bandTracks).join(` ${groupGap}px `)
|
|
8235
8400
|
};
|
|
8236
8401
|
if (compact) {
|
|
8237
8402
|
gridStyle["--a8c-charts-dimension-heatmap-cell-gap"] = `${compactCellGap}px`;
|
|
8238
|
-
gridStyle["--a8c-charts-dimension-heatmap-cell-size"] = `${compactCellSize}px`;
|
|
8403
|
+
gridStyle["--a8c-charts-dimension-heatmap-cell-size"] = `${fit?.cellSize ?? compactCellSize}px`;
|
|
8239
8404
|
}
|
|
8240
8405
|
const summaryGaps = (columnIndex) => {
|
|
8241
8406
|
if (!data[columnIndex]?.summary) return {};
|
|
@@ -8255,6 +8420,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8255
8420
|
legendChildren: [],
|
|
8256
8421
|
trailingContent: nonLegendChildren,
|
|
8257
8422
|
gap,
|
|
8423
|
+
rootRef: chartRef,
|
|
8258
8424
|
className: (0, clsx.default)("heatmap-chart", heatmap_chart_module_default["heatmap-chart"], className, { [heatmap_chart_module_default["heatmap-chart--height-capped"]]: heightCapped }),
|
|
8259
8425
|
style: {
|
|
8260
8426
|
width: width || void 0,
|
|
@@ -8284,11 +8450,11 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8284
8450
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8285
8451
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: {
|
|
8286
8452
|
gridColumn: 1,
|
|
8287
|
-
gridRow:
|
|
8453
|
+
gridRow: labelRowOf(0)
|
|
8288
8454
|
} }), data.map((column, columnIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8289
8455
|
style: {
|
|
8290
8456
|
gridColumn: columnLine(columnIndex),
|
|
8291
|
-
gridRow:
|
|
8457
|
+
gridRow: labelRowOf(bandOf(columnIndex))
|
|
8292
8458
|
},
|
|
8293
8459
|
className: (0, clsx.default)(heatmap_chart_module_default["heatmap-chart__col-label"], {
|
|
8294
8460
|
[heatmap_chart_module_default["heatmap-chart__col-label--summary"]]: column.summary,
|
|
@@ -8299,24 +8465,23 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8299
8465
|
}),
|
|
8300
8466
|
Array.from({ length: rows }).map((_row, rowIndex) => {
|
|
8301
8467
|
const labelVisible = !compact || rowIndex % 2 === 0;
|
|
8302
|
-
const gridRow = firstDataRow + rowIndex;
|
|
8303
8468
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8304
8469
|
role: "row",
|
|
8305
8470
|
"aria-rowindex": rowIndex + 1,
|
|
8306
8471
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8307
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8472
|
+
children: [Array.from({ length: bands }).map((_band, band) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8308
8473
|
"aria-hidden": "true",
|
|
8309
8474
|
className: heatmap_chart_module_default["heatmap-chart__row-label"],
|
|
8310
8475
|
style: {
|
|
8311
8476
|
gridColumn: 1,
|
|
8312
|
-
gridRow
|
|
8477
|
+
gridRow: dataRowOf(band, rowIndex)
|
|
8313
8478
|
},
|
|
8314
8479
|
children: labelVisible ? rowLabels[rowIndex] ?? "" : ""
|
|
8315
|
-
}), data.map((column, columnIndex) => {
|
|
8480
|
+
}, `row-label-${band}`)), data.map((column, columnIndex) => {
|
|
8316
8481
|
const cell = column.data[rowIndex];
|
|
8317
8482
|
const placement = {
|
|
8318
8483
|
gridColumn: columnLine(columnIndex),
|
|
8319
|
-
gridRow
|
|
8484
|
+
gridRow: dataRowOf(bandOf(columnIndex), rowIndex)
|
|
8320
8485
|
};
|
|
8321
8486
|
if (cell?.hidden) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8322
8487
|
"aria-hidden": "true",
|
|
@@ -8366,11 +8531,11 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8366
8531
|
role: "row",
|
|
8367
8532
|
"aria-hidden": "true",
|
|
8368
8533
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8369
|
-
children:
|
|
8534
|
+
children: placed.groups.map((group, groupIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8370
8535
|
className: heatmap_chart_module_default["heatmap-chart__group-label"],
|
|
8371
8536
|
style: {
|
|
8372
8537
|
gridColumn: `${group.line} / span ${group.span}`,
|
|
8373
|
-
gridRow:
|
|
8538
|
+
gridRow: dataRowOf(group.band, rows)
|
|
8374
8539
|
},
|
|
8375
8540
|
children: group.label
|
|
8376
8541
|
}, `group-${groupIndex}`))
|
|
@@ -11605,6 +11770,7 @@ var leaderboard_chart_module_default = {
|
|
|
11605
11770
|
"interactiveRow": "a8ccharts-GovfoW-interactiveRow",
|
|
11606
11771
|
"is-overlay": "a8ccharts-GovfoW-is-overlay",
|
|
11607
11772
|
"label": "a8ccharts-GovfoW-label",
|
|
11773
|
+
"layeredRow": "a8ccharts-GovfoW-layeredRow",
|
|
11608
11774
|
"leaderboardChart": "a8ccharts-GovfoW-leaderboardChart",
|
|
11609
11775
|
"leaderboardChart__content": "a8ccharts-GovfoW-leaderboardChart__content",
|
|
11610
11776
|
"leaderboardChart__content--fit": "a8ccharts-GovfoW-leaderboardChart__content--fit",
|
|
@@ -11613,6 +11779,7 @@ var leaderboard_chart_module_default = {
|
|
|
11613
11779
|
"overlap": "a8ccharts-GovfoW-overlap",
|
|
11614
11780
|
"overlayLabel": "a8ccharts-GovfoW-overlayLabel",
|
|
11615
11781
|
"row": "a8ccharts-GovfoW-row",
|
|
11782
|
+
"rowButton": "a8ccharts-GovfoW-rowButton",
|
|
11616
11783
|
"stretch": "a8ccharts-GovfoW-stretch",
|
|
11617
11784
|
"valueContainer": "a8ccharts-GovfoW-valueContainer"
|
|
11618
11785
|
};
|
|
@@ -11663,6 +11830,16 @@ const defaultDeltaFormatter = (value) => {
|
|
|
11663
11830
|
const getBarWidth = (share) => `calc(${share}% - var(--a8c-charts-dimension-leaderboard-bar-hover-inset, 0px) * ${share} / 100)`;
|
|
11664
11831
|
const hasPreviousValue = (entry) => entry.previousValue != null && entry.previousShare != null;
|
|
11665
11832
|
const hasDeltaValue = (entry) => hasPreviousValue(entry) && entry.delta != null;
|
|
11833
|
+
/**
|
|
11834
|
+
* A layered row's cell that takes pointer events of its own (a value tooltip)
|
|
11835
|
+
* sits above the row button; pass its clicks on so they still drill down.
|
|
11836
|
+
*
|
|
11837
|
+
* @param event - The click on the row.
|
|
11838
|
+
*/
|
|
11839
|
+
function forwardCellClickToRowButton(event) {
|
|
11840
|
+
if (event.target.closest("a, button")) return;
|
|
11841
|
+
event.currentTarget.querySelector(":scope > button")?.click();
|
|
11842
|
+
}
|
|
11666
11843
|
const BarLabel = ({ label }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: typeof label === "string" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_ui.Text, {
|
|
11667
11844
|
className: leaderboard_chart_module_default.label,
|
|
11668
11845
|
children: label
|
|
@@ -11895,6 +12072,26 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
|
|
|
11895
12072
|
})
|
|
11896
12073
|
]
|
|
11897
12074
|
})] });
|
|
12075
|
+
if (entry.onClick && entry.hasInteractiveLabel) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
12076
|
+
"data-row-index": rowIndex,
|
|
12077
|
+
style: rowStyle,
|
|
12078
|
+
className: (0, clsx.default)(leaderboard_chart_module_default.row, leaderboard_chart_module_default.interactiveRow, leaderboard_chart_module_default.layeredRow),
|
|
12079
|
+
onClick: forwardCellClickToRowButton,
|
|
12080
|
+
children: [
|
|
12081
|
+
rowCells,
|
|
12082
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
12083
|
+
type: "button",
|
|
12084
|
+
className: leaderboard_chart_module_default.rowButton,
|
|
12085
|
+
onClick: entry.onClick,
|
|
12086
|
+
"aria-label": entry.ariaLabel
|
|
12087
|
+
}),
|
|
12088
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_icons.Icon, {
|
|
12089
|
+
className: leaderboard_chart_module_default.chevron,
|
|
12090
|
+
icon: _wordpress_icons.chevronRight,
|
|
12091
|
+
size: 24
|
|
12092
|
+
})
|
|
12093
|
+
]
|
|
12094
|
+
}, entry.id);
|
|
11898
12095
|
if (entry.onClick) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
11899
12096
|
type: "button",
|
|
11900
12097
|
"data-row-index": rowIndex,
|
|
@@ -11928,6 +12125,210 @@ LeaderboardChartWithProvider.displayName = "LeaderboardChart";
|
|
|
11928
12125
|
const LeaderboardChart = attachSubComponents(LeaderboardChartWithProvider, { Legend });
|
|
11929
12126
|
const LeaderboardChartResponsive = attachSubComponents(withResponsive(LeaderboardChartWithProvider), { Legend });
|
|
11930
12127
|
//#endregion
|
|
12128
|
+
//#region src/charts/private/pie-keyboard-navigation/order-arcs-for-navigation.ts
|
|
12129
|
+
/**
|
|
12130
|
+
* Orders arcs the way they appear: clockwise from 12 o'clock, which for a semi-circle is left to right.
|
|
12131
|
+
*
|
|
12132
|
+
* @param arcs - Arcs from visx's `pie` factory, in data order.
|
|
12133
|
+
* @return A copy of `arcs` sorted by angular midpoint.
|
|
12134
|
+
*/
|
|
12135
|
+
const orderArcsForNavigation = (arcs) => [...arcs].sort((a, b) => a.startAngle + a.endAngle - (b.startAngle + b.endAngle));
|
|
12136
|
+
//#endregion
|
|
12137
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-selection-announcement.tsx
|
|
12138
|
+
const PieSelectionAnnouncement = ({ data }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_ui.VisuallyHidden, {
|
|
12139
|
+
role: "status",
|
|
12140
|
+
"aria-atomic": "true",
|
|
12141
|
+
children: data && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LabelValueContent, { data })
|
|
12142
|
+
});
|
|
12143
|
+
//#endregion
|
|
12144
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-tooltip.tsx
|
|
12145
|
+
const PieTooltip = ({ top, left, selectedIndex, tooltipRef, children }) => {
|
|
12146
|
+
const standaloneScopeClass = useStandaloneScopeClass();
|
|
12147
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BoundedTooltip, {
|
|
12148
|
+
top,
|
|
12149
|
+
left,
|
|
12150
|
+
children: selectedIndex === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12151
|
+
className: standaloneScopeClass,
|
|
12152
|
+
role: "tooltip",
|
|
12153
|
+
children
|
|
12154
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12155
|
+
ref: tooltipRef,
|
|
12156
|
+
tabIndex: -1,
|
|
12157
|
+
role: "tooltip",
|
|
12158
|
+
"aria-atomic": "true",
|
|
12159
|
+
className: standaloneScopeClass,
|
|
12160
|
+
children
|
|
12161
|
+
}, `chart-tooltip-${selectedIndex}`)
|
|
12162
|
+
});
|
|
12163
|
+
};
|
|
12164
|
+
//#endregion
|
|
12165
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-selection-output.tsx
|
|
12166
|
+
/**
|
|
12167
|
+
* Reports the selected segment: a focused tooltip for a keyboard selection, a pointer tooltip on hover, or a screen reader announcement without tooltips.
|
|
12168
|
+
*
|
|
12169
|
+
* @param {PieSelectionOutputProps} props - Component props
|
|
12170
|
+
* @return {JSX.Element} The announcement region and the tooltip, if any
|
|
12171
|
+
*/
|
|
12172
|
+
const PieSelectionOutput = ({ withTooltips, selectedIndex, selectedData, keyboardTooltipAnchor, pointerTooltip, chartRef, svgRef, tooltipRef, renderTooltip }) => {
|
|
12173
|
+
const [svgOffset, setSvgOffset] = (0, react.useState)({
|
|
12174
|
+
top: 0,
|
|
12175
|
+
left: 0
|
|
12176
|
+
});
|
|
12177
|
+
const showKeyboardTooltip = withTooltips && selectedData && keyboardTooltipAnchor;
|
|
12178
|
+
(0, react.useLayoutEffect)(() => {
|
|
12179
|
+
const chartBounds = chartRef.current?.getBoundingClientRect();
|
|
12180
|
+
const svgBounds = svgRef.current?.getBoundingClientRect();
|
|
12181
|
+
if (!showKeyboardTooltip || !chartBounds || !svgBounds) return;
|
|
12182
|
+
const top = svgBounds.top - chartBounds.top;
|
|
12183
|
+
const left = svgBounds.left - chartBounds.left;
|
|
12184
|
+
setSvgOffset((current) => current.top === top && current.left === left ? current : {
|
|
12185
|
+
top,
|
|
12186
|
+
left
|
|
12187
|
+
});
|
|
12188
|
+
});
|
|
12189
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
12190
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PieSelectionAnnouncement, { data: withTooltips ? void 0 : selectedData }),
|
|
12191
|
+
showKeyboardTooltip && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PieTooltip, {
|
|
12192
|
+
top: svgOffset.top + keyboardTooltipAnchor.top,
|
|
12193
|
+
left: svgOffset.left + keyboardTooltipAnchor.left,
|
|
12194
|
+
selectedIndex,
|
|
12195
|
+
tooltipRef,
|
|
12196
|
+
children: renderTooltip({ tooltipData: selectedData })
|
|
12197
|
+
}),
|
|
12198
|
+
withTooltips && !selectedData && pointerTooltip?.data && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PieTooltip, {
|
|
12199
|
+
top: pointerTooltip.top,
|
|
12200
|
+
left: pointerTooltip.left,
|
|
12201
|
+
children: renderTooltip({ tooltipData: pointerTooltip.data })
|
|
12202
|
+
})
|
|
12203
|
+
] });
|
|
12204
|
+
};
|
|
12205
|
+
//#endregion
|
|
12206
|
+
//#region src/charts/private/pie-keyboard-navigation/pie-keyboard-navigation.module.scss
|
|
12207
|
+
var pie_keyboard_navigation_module_default = {
|
|
12208
|
+
"selected-ring__contrast": "a8ccharts-V2HDKq-selected-ring__contrast",
|
|
12209
|
+
"selected-ring__focus": "a8ccharts-V2HDKq-selected-ring__focus"
|
|
12210
|
+
};
|
|
12211
|
+
//#endregion
|
|
12212
|
+
//#region src/charts/private/pie-keyboard-navigation/selected-segment-ring.tsx
|
|
12213
|
+
/**
|
|
12214
|
+
* Encodes `value` for an SVG id, losslessly so distinct chart ids never share a clip path.
|
|
12215
|
+
*
|
|
12216
|
+
* @param value - Any string.
|
|
12217
|
+
* @return `value` with each character outside `[A-Za-z0-9-]` written as `_<hex code point>_`.
|
|
12218
|
+
*/
|
|
12219
|
+
const toSvgId = (value) => Array.from(value, (character) => /[A-Za-z0-9-]/.test(character) ? character : `_${character.codePointAt(0)?.toString(16)}_`).join("");
|
|
12220
|
+
/**
|
|
12221
|
+
* Marks the selected segment with a two-tone ring drawn inside its edge, so the SVG edge cannot cut it off.
|
|
12222
|
+
*
|
|
12223
|
+
* @param {SelectedSegmentRingProps} props - Component props
|
|
12224
|
+
* @return {JSX.Element} The ring
|
|
12225
|
+
*/
|
|
12226
|
+
const SelectedSegmentRing = ({ chartId, d }) => {
|
|
12227
|
+
const clipId = `pie-selected-ring-clip-${toSvgId(chartId)}`;
|
|
12228
|
+
const clipPath = `url(#${clipId})`;
|
|
12229
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
12230
|
+
pointerEvents: "none",
|
|
12231
|
+
"aria-hidden": "true",
|
|
12232
|
+
children: [
|
|
12233
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("clipPath", {
|
|
12234
|
+
id: clipId,
|
|
12235
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d })
|
|
12236
|
+
}),
|
|
12237
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
12238
|
+
d,
|
|
12239
|
+
clipPath,
|
|
12240
|
+
className: pie_keyboard_navigation_module_default["selected-ring__contrast"]
|
|
12241
|
+
}),
|
|
12242
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
12243
|
+
d,
|
|
12244
|
+
clipPath,
|
|
12245
|
+
className: pie_keyboard_navigation_module_default["selected-ring__focus"]
|
|
12246
|
+
})
|
|
12247
|
+
]
|
|
12248
|
+
});
|
|
12249
|
+
};
|
|
12250
|
+
//#endregion
|
|
12251
|
+
//#region src/charts/private/pie-keyboard-navigation/use-pie-keyboard-navigation.ts
|
|
12252
|
+
const usePieKeyboardNavigation = ({ navigationArcs, withTooltips, tooltipOffsetX, tooltipOffsetY }) => {
|
|
12253
|
+
const chartRef = (0, react.useRef)(null);
|
|
12254
|
+
const svgRef = (0, react.useRef)(null);
|
|
12255
|
+
const [selectedIndex, setSelectedIndex] = (0, react.useState)(void 0);
|
|
12256
|
+
const [isNavigating, setIsNavigating] = (0, react.useState)(false);
|
|
12257
|
+
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = (0, _visx_tooltip.useTooltip)();
|
|
12258
|
+
const { tooltipRef: focusTooltip, onChartFocus, onChartBlur, onChartKeyDown, onChartPointerMove } = useKeyboardNavigation({
|
|
12259
|
+
selectedIndex,
|
|
12260
|
+
setSelectedIndex,
|
|
12261
|
+
isNavigating,
|
|
12262
|
+
setIsNavigating,
|
|
12263
|
+
chartRef,
|
|
12264
|
+
totalPoints: navigationArcs.length,
|
|
12265
|
+
visibleSeriesKey: JSON.stringify(navigationArcs.map((arcDatum) => arcDatum.data.label))
|
|
12266
|
+
});
|
|
12267
|
+
const selectedArc = selectedIndex === void 0 ? void 0 : navigationArcs[selectedIndex];
|
|
12268
|
+
const keyboardTooltip = (0, react.useRef)(null);
|
|
12269
|
+
const tooltipLostFocus = (0, react.useRef)(false);
|
|
12270
|
+
const tooltipRef = (0, react.useCallback)((element) => {
|
|
12271
|
+
if (element) {
|
|
12272
|
+
keyboardTooltip.current = element;
|
|
12273
|
+
focusTooltip(element);
|
|
12274
|
+
} else if (keyboardTooltip.current?.ownerDocument.activeElement === keyboardTooltip.current) tooltipLostFocus.current = true;
|
|
12275
|
+
}, [focusTooltip]);
|
|
12276
|
+
(0, react.useLayoutEffect)(() => {
|
|
12277
|
+
if (!tooltipLostFocus.current) return;
|
|
12278
|
+
tooltipLostFocus.current = false;
|
|
12279
|
+
const { activeElement, body } = chartRef.current?.ownerDocument ?? document;
|
|
12280
|
+
if (activeElement === null || activeElement === body) chartRef.current?.focus();
|
|
12281
|
+
});
|
|
12282
|
+
const getSegmentHandlers = (data, navigationIndex) => ({
|
|
12283
|
+
onMouseMove: (event) => {
|
|
12284
|
+
onChartPointerMove(navigationIndex);
|
|
12285
|
+
if (!withTooltips) return;
|
|
12286
|
+
const bounds = chartRef.current?.getBoundingClientRect();
|
|
12287
|
+
if (!bounds) return;
|
|
12288
|
+
showTooltip({
|
|
12289
|
+
tooltipData: data,
|
|
12290
|
+
tooltipLeft: event.clientX - bounds.left + tooltipOffsetX,
|
|
12291
|
+
tooltipTop: event.clientY - bounds.top + tooltipOffsetY
|
|
12292
|
+
});
|
|
12293
|
+
},
|
|
12294
|
+
onMouseLeave: withTooltips ? hideTooltip : void 0
|
|
12295
|
+
});
|
|
12296
|
+
return {
|
|
12297
|
+
chartRef,
|
|
12298
|
+
svgRef,
|
|
12299
|
+
selectedArc,
|
|
12300
|
+
getSegmentHandlers,
|
|
12301
|
+
getKeyboardTooltipAnchor: (0, react.useCallback)((originX, originY, [x, y]) => withTooltips ? {
|
|
12302
|
+
left: originX + x + tooltipOffsetX,
|
|
12303
|
+
top: originY + y + tooltipOffsetY
|
|
12304
|
+
} : void 0, [
|
|
12305
|
+
withTooltips,
|
|
12306
|
+
tooltipOffsetX,
|
|
12307
|
+
tooltipOffsetY
|
|
12308
|
+
]),
|
|
12309
|
+
selectionOutputProps: {
|
|
12310
|
+
withTooltips,
|
|
12311
|
+
selectedIndex,
|
|
12312
|
+
selectedData: selectedArc?.data,
|
|
12313
|
+
chartRef,
|
|
12314
|
+
svgRef,
|
|
12315
|
+
tooltipRef,
|
|
12316
|
+
pointerTooltip: tooltipOpen ? {
|
|
12317
|
+
data: tooltipData,
|
|
12318
|
+
left: tooltipLeft || 0,
|
|
12319
|
+
top: tooltipTop || 0
|
|
12320
|
+
} : void 0
|
|
12321
|
+
},
|
|
12322
|
+
chartProps: {
|
|
12323
|
+
role: "application",
|
|
12324
|
+
tabIndex: 0,
|
|
12325
|
+
onKeyDown: onChartKeyDown,
|
|
12326
|
+
onFocus: onChartFocus,
|
|
12327
|
+
onBlur: onChartBlur
|
|
12328
|
+
}
|
|
12329
|
+
};
|
|
12330
|
+
};
|
|
12331
|
+
//#endregion
|
|
11931
12332
|
//#region src/charts/private/radial-wipe-animation/radial-wipe-animation.tsx
|
|
11932
12333
|
/**
|
|
11933
12334
|
* Renders a SVG mask that creates a radial wipe animation effect.
|
|
@@ -12023,20 +12424,13 @@ const LABEL_TEXT_MODIFIER = {
|
|
|
12023
12424
|
* @param {PieChartProps} props - Component props
|
|
12024
12425
|
* @return {JSX.Element} The rendered chart component
|
|
12025
12426
|
*/
|
|
12026
|
-
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" }) => {
|
|
12427
|
+
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" }) => {
|
|
12027
12428
|
const legendInteractive = legend.interactive ?? false;
|
|
12028
12429
|
const legendPosition = legend.position ?? "bottom";
|
|
12029
12430
|
const providerTheme = useGlobalChartsTheme();
|
|
12030
12431
|
const chartId = useChartId(providedChartId);
|
|
12031
|
-
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = (0, _visx_tooltip.useTooltip)();
|
|
12032
|
-
const standaloneScopeClass = useStandaloneScopeClass();
|
|
12033
|
-
const containerRef = (0, react.useRef)(null);
|
|
12034
12432
|
const rootRef = (0, react.useRef)(null);
|
|
12035
12433
|
const [labelRoles, setLabelRoles] = (0, react.useState)(null);
|
|
12036
|
-
const onMouseLeave = (0, react.useCallback)(() => {
|
|
12037
|
-
if (!withTooltips) return;
|
|
12038
|
-
hideTooltip();
|
|
12039
|
-
}, [withTooltips, hideTooltip]);
|
|
12040
12434
|
const { getElementStyles, isSeriesVisible, isColorPaletteResolved } = useGlobalChartsContext();
|
|
12041
12435
|
const { isValid, message } = validateData$1(data);
|
|
12042
12436
|
(0, react.useLayoutEffect)(() => {
|
|
@@ -12080,13 +12474,7 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
12080
12474
|
metadata: chartMetadata
|
|
12081
12475
|
});
|
|
12082
12476
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
12083
|
-
|
|
12084
|
-
className: (0, clsx.default)("pie-chart", pie_chart_module_default["pie-chart"], className),
|
|
12085
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12086
|
-
className: pie_chart_module_default["error-message"],
|
|
12087
|
-
children: message
|
|
12088
|
-
})
|
|
12089
|
-
});
|
|
12477
|
+
const wipeMask = animation && !prefersReducedMotion ? `url(#radial-wipe-${chartId})` : null;
|
|
12090
12478
|
const padAngle = gapScale * (2 * Math.PI / data.length);
|
|
12091
12479
|
const dataWithIndex = visibleData.map((d) => {
|
|
12092
12480
|
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
@@ -12104,6 +12492,24 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
12104
12492
|
}).color;
|
|
12105
12493
|
}
|
|
12106
12494
|
};
|
|
12495
|
+
const arcs = (0, _visx_shape.pie)({
|
|
12496
|
+
value: accessors.value,
|
|
12497
|
+
padAngle
|
|
12498
|
+
})(dataWithIndex);
|
|
12499
|
+
const navigationArcs = orderArcsForNavigation(arcs);
|
|
12500
|
+
const { chartRef, svgRef, selectedArc, getSegmentHandlers, getKeyboardTooltipAnchor, selectionOutputProps, chartProps } = usePieKeyboardNavigation({
|
|
12501
|
+
navigationArcs,
|
|
12502
|
+
withTooltips,
|
|
12503
|
+
tooltipOffsetX,
|
|
12504
|
+
tooltipOffsetY
|
|
12505
|
+
});
|
|
12506
|
+
if (!isValid) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12507
|
+
className: (0, clsx.default)("pie-chart", pie_chart_module_default["pie-chart"], className),
|
|
12508
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12509
|
+
className: pie_chart_module_default["error-message"],
|
|
12510
|
+
children: message
|
|
12511
|
+
})
|
|
12512
|
+
});
|
|
12107
12513
|
const legendElement = showLegend && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Legend, {
|
|
12108
12514
|
orientation: legend.orientation ?? "horizontal",
|
|
12109
12515
|
position: legendPosition,
|
|
@@ -12142,102 +12548,96 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
12142
12548
|
const innerRadius = thickness === 0 ? 0 : outerRadius * (1 - thickness);
|
|
12143
12549
|
const maxCornerRadius = (outerRadius - innerRadius) / 2;
|
|
12144
12550
|
const cornerRadius = cornerScale ? Math.min(cornerScale * outerRadius, maxCornerRadius) : 0;
|
|
12551
|
+
const path = (0, _visx_shape.arc)({
|
|
12552
|
+
innerRadius,
|
|
12553
|
+
outerRadius,
|
|
12554
|
+
cornerRadius
|
|
12555
|
+
});
|
|
12556
|
+
const svgLabelSmall = providerTheme.svgLabelSmall;
|
|
12557
|
+
const fontSize = resolveFontSize(svgLabelSmall?.fontSize) ?? 12;
|
|
12558
|
+
const renderLabel = (arcDatum, index) => {
|
|
12559
|
+
if (arcDatum.endAngle - arcDatum.startAngle < .25) return null;
|
|
12560
|
+
const [centroidX, centroidY] = path.centroid(arcDatum);
|
|
12561
|
+
const backgroundWidth = (0, _visx_text.getStringWidth)(arcDatum.data.label, {
|
|
12562
|
+
fontSize,
|
|
12563
|
+
fontFamily: svgLabelSmall?.fontFamily,
|
|
12564
|
+
fontWeight: svgLabelSmall?.fontWeight
|
|
12565
|
+
}) + 12;
|
|
12566
|
+
const backgroundHeight = fontSize + 12;
|
|
12567
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
12568
|
+
className: pie_chart_module_default["pie-chart__label-plate"],
|
|
12569
|
+
x: centroidX - backgroundWidth / 2,
|
|
12570
|
+
y: centroidY - backgroundHeight / 2,
|
|
12571
|
+
width: backgroundWidth,
|
|
12572
|
+
height: backgroundHeight,
|
|
12573
|
+
rx: 4,
|
|
12574
|
+
ry: 4,
|
|
12575
|
+
pointerEvents: "none"
|
|
12576
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
12577
|
+
className: (0, clsx.default)(pie_chart_module_default["pie-chart__label-text"], LABEL_TEXT_MODIFIER[pickLabelTextColor(accessors.fill(arcDatum.data), labelRoles, "label-inverse")]),
|
|
12578
|
+
x: centroidX,
|
|
12579
|
+
y: centroidY,
|
|
12580
|
+
dy: ".33em",
|
|
12581
|
+
fontSize,
|
|
12582
|
+
textAnchor: "middle",
|
|
12583
|
+
pointerEvents: "none",
|
|
12584
|
+
children: arcDatum.data.label
|
|
12585
|
+
})] }, `label-${index}`);
|
|
12586
|
+
};
|
|
12145
12587
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Center, {
|
|
12146
|
-
ref:
|
|
12588
|
+
ref: chartRef,
|
|
12147
12589
|
className: pie_chart_module_default["pie-chart__plot"],
|
|
12590
|
+
...chartProps,
|
|
12591
|
+
"aria-label": ariaLabel ?? (0, _wordpress_i18n.__)("Pie chart", "jetpack-charts"),
|
|
12148
12592
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
12593
|
+
ref: svgRef,
|
|
12149
12594
|
viewBox: `0 0 ${width} ${height}`,
|
|
12150
12595
|
preserveAspectRatio: "xMidYMid meet",
|
|
12151
12596
|
width,
|
|
12152
12597
|
height,
|
|
12153
|
-
children: [
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
|
|
12174
|
-
|
|
12175
|
-
|
|
12176
|
-
|
|
12177
|
-
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
groupProps.onMouseMove = handleMouseMove;
|
|
12197
|
-
groupProps.onMouseLeave = onMouseLeave;
|
|
12198
|
-
}
|
|
12199
|
-
const svgLabelSmall = providerTheme.svgLabelSmall;
|
|
12200
|
-
const fontSize = resolveFontSize(svgLabelSmall?.fontSize) ?? 12;
|
|
12201
|
-
const backgroundWidth = (0, _visx_text.getStringWidth)(arc.data.label, {
|
|
12202
|
-
fontSize,
|
|
12203
|
-
fontFamily: svgLabelSmall?.fontFamily,
|
|
12204
|
-
fontWeight: svgLabelSmall?.fontWeight
|
|
12205
|
-
}) + 12;
|
|
12206
|
-
const backgroundHeight = fontSize + 12;
|
|
12207
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
12208
|
-
...groupProps,
|
|
12209
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { ...pathProps }), showLabels && hasSpaceForLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
12210
|
-
className: pie_chart_module_default["pie-chart__label-plate"],
|
|
12211
|
-
x: centroidX - backgroundWidth / 2,
|
|
12212
|
-
y: centroidY - backgroundHeight / 2,
|
|
12213
|
-
width: backgroundWidth,
|
|
12214
|
-
height: backgroundHeight,
|
|
12215
|
-
rx: 4,
|
|
12216
|
-
ry: 4,
|
|
12217
|
-
pointerEvents: "none"
|
|
12218
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
12219
|
-
className: (0, clsx.default)(pie_chart_module_default["pie-chart__label-text"], LABEL_TEXT_MODIFIER[pickLabelTextColor(fill, labelRoles, "label-inverse")]),
|
|
12220
|
-
x: centroidX,
|
|
12221
|
-
y: centroidY,
|
|
12222
|
-
dy: ".33em",
|
|
12223
|
-
fontSize,
|
|
12224
|
-
textAnchor: "middle",
|
|
12225
|
-
pointerEvents: "none",
|
|
12226
|
-
children: arc.data.label
|
|
12227
|
-
})] })]
|
|
12228
|
-
}, `arc-${index}`);
|
|
12229
|
-
});
|
|
12230
|
-
}
|
|
12231
|
-
}), !allSegmentsHidden && svgChildren]
|
|
12232
|
-
})]
|
|
12233
|
-
}), withTooltips && tooltipOpen && tooltipData && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BoundedTooltip, {
|
|
12234
|
-
top: tooltipTop || 0,
|
|
12235
|
-
left: tooltipLeft || 0,
|
|
12236
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12237
|
-
className: standaloneScopeClass,
|
|
12238
|
-
role: "tooltip",
|
|
12239
|
-
children: renderTooltip({ tooltipData })
|
|
12240
|
-
})
|
|
12598
|
+
children: [
|
|
12599
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RadialWipeAnimation, {
|
|
12600
|
+
id: `radial-wipe-${chartId}`,
|
|
12601
|
+
radius: outerRadius,
|
|
12602
|
+
innerRadius
|
|
12603
|
+
}) }),
|
|
12604
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_group.Group, {
|
|
12605
|
+
top: centerY,
|
|
12606
|
+
left: centerX,
|
|
12607
|
+
mask: wipeMask,
|
|
12608
|
+
children: allSegmentsHidden ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SvgEmptyState, {
|
|
12609
|
+
x: 0,
|
|
12610
|
+
y: 0,
|
|
12611
|
+
width,
|
|
12612
|
+
height,
|
|
12613
|
+
children: getAllHiddenMessage(legendInteractive, "segments")
|
|
12614
|
+
}) : arcs.map((arcDatum, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("g", {
|
|
12615
|
+
...getSegmentHandlers(arcDatum.data, navigationArcs.indexOf(arcDatum)),
|
|
12616
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
12617
|
+
d: path(arcDatum) || "",
|
|
12618
|
+
fill: accessors.fill(arcDatum.data)
|
|
12619
|
+
})
|
|
12620
|
+
}, `arc-${index}`))
|
|
12621
|
+
}),
|
|
12622
|
+
selectedArc && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_group.Group, {
|
|
12623
|
+
top: centerY,
|
|
12624
|
+
left: centerX,
|
|
12625
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectedSegmentRing, {
|
|
12626
|
+
chartId,
|
|
12627
|
+
d: path(selectedArc) || ""
|
|
12628
|
+
})
|
|
12629
|
+
}),
|
|
12630
|
+
!allSegmentsHidden && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_group.Group, {
|
|
12631
|
+
top: centerY,
|
|
12632
|
+
left: centerX,
|
|
12633
|
+
mask: wipeMask,
|
|
12634
|
+
children: [showLabels && arcs.map(renderLabel), svgChildren]
|
|
12635
|
+
})
|
|
12636
|
+
]
|
|
12637
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PieSelectionOutput, {
|
|
12638
|
+
...selectionOutputProps,
|
|
12639
|
+
keyboardTooltipAnchor: selectedArc && getKeyboardTooltipAnchor(centerX, centerY, path.centroid(selectedArc)),
|
|
12640
|
+
renderTooltip
|
|
12241
12641
|
})]
|
|
12242
12642
|
});
|
|
12243
12643
|
}
|
|
@@ -12305,32 +12705,10 @@ const validateData = (data) => {
|
|
|
12305
12705
|
message: ""
|
|
12306
12706
|
};
|
|
12307
12707
|
};
|
|
12308
|
-
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" }) => {
|
|
12708
|
+
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" }) => {
|
|
12309
12709
|
const legendInteractive = legend.interactive ?? false;
|
|
12310
12710
|
const legendPosition = legend.position ?? "bottom";
|
|
12311
12711
|
const chartId = useChartId(providedChartId);
|
|
12312
|
-
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = (0, _visx_tooltip.useTooltip)();
|
|
12313
|
-
const standaloneScopeClass = useStandaloneScopeClass();
|
|
12314
|
-
const containerRef = (0, react.useRef)(null);
|
|
12315
|
-
const handleMouseMove = (0, react.useCallback)((event, arc) => {
|
|
12316
|
-
const bounds = containerRef.current?.getBoundingClientRect();
|
|
12317
|
-
if (!bounds) return;
|
|
12318
|
-
showTooltip({
|
|
12319
|
-
tooltipData: arc.data,
|
|
12320
|
-
tooltipLeft: event.clientX - bounds.left + tooltipOffsetX,
|
|
12321
|
-
tooltipTop: event.clientY - bounds.top + tooltipOffsetY
|
|
12322
|
-
});
|
|
12323
|
-
}, [
|
|
12324
|
-
showTooltip,
|
|
12325
|
-
tooltipOffsetX,
|
|
12326
|
-
tooltipOffsetY
|
|
12327
|
-
]);
|
|
12328
|
-
const handleMouseLeave = (0, react.useCallback)(() => {
|
|
12329
|
-
hideTooltip();
|
|
12330
|
-
}, [hideTooltip]);
|
|
12331
|
-
const handleArcMouseMove = (0, react.useCallback)((arc) => (event) => {
|
|
12332
|
-
handleMouseMove(event, arc);
|
|
12333
|
-
}, [handleMouseMove]);
|
|
12334
12712
|
const { isValid, message } = validateData(data);
|
|
12335
12713
|
const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
|
|
12336
12714
|
const dataWithPercentages = useDataWithPercentages(data);
|
|
@@ -12364,7 +12742,31 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
12364
12742
|
metadata: chartMetadata
|
|
12365
12743
|
});
|
|
12366
12744
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
12745
|
+
const wipeMask = animation && !prefersReducedMotion ? `url(#radial-wipe-${chartId})` : null;
|
|
12367
12746
|
const effectiveWidth = propWidth || DEFAULT_WIDTH$1;
|
|
12747
|
+
const dataWithIndex = visibleData.map((d) => {
|
|
12748
|
+
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
12749
|
+
return {
|
|
12750
|
+
...d,
|
|
12751
|
+
index: originalIndex >= 0 ? originalIndex : 0
|
|
12752
|
+
};
|
|
12753
|
+
});
|
|
12754
|
+
const startAngle = clockwise ? -Math.PI / 2 : Math.PI / 2;
|
|
12755
|
+
const endAngle = clockwise ? Math.PI / 2 : -Math.PI / 2;
|
|
12756
|
+
const arcs = (0, _visx_shape.pie)({
|
|
12757
|
+
value: accessors.value,
|
|
12758
|
+
sort: accessors.sort,
|
|
12759
|
+
padAngle: PAD_ANGLE,
|
|
12760
|
+
startAngle,
|
|
12761
|
+
endAngle
|
|
12762
|
+
})(dataWithIndex);
|
|
12763
|
+
const navigationArcs = orderArcsForNavigation(arcs);
|
|
12764
|
+
const { chartRef, svgRef, selectedArc, getSegmentHandlers, getKeyboardTooltipAnchor, selectionOutputProps, chartProps } = usePieKeyboardNavigation({
|
|
12765
|
+
navigationArcs,
|
|
12766
|
+
withTooltips,
|
|
12767
|
+
tooltipOffsetX,
|
|
12768
|
+
tooltipOffsetY
|
|
12769
|
+
});
|
|
12368
12770
|
if (!isValid) {
|
|
12369
12771
|
const errorWidth = propHeight ? Math.min(propWidth || propHeight * 2, propHeight * 2) : effectiveWidth;
|
|
12370
12772
|
const errorHeight = errorWidth / 2;
|
|
@@ -12383,15 +12785,6 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
12383
12785
|
})
|
|
12384
12786
|
});
|
|
12385
12787
|
}
|
|
12386
|
-
const dataWithIndex = visibleData.map((d) => {
|
|
12387
|
-
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
12388
|
-
return {
|
|
12389
|
-
...d,
|
|
12390
|
-
index: originalIndex >= 0 ? originalIndex : 0
|
|
12391
|
-
};
|
|
12392
|
-
});
|
|
12393
|
-
const startAngle = clockwise ? -Math.PI / 2 : Math.PI / 2;
|
|
12394
|
-
const endAngle = clockwise ? Math.PI / 2 : -Math.PI / 2;
|
|
12395
12788
|
const legendElement = showLegend && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Legend, {
|
|
12396
12789
|
orientation: legend.orientation ?? "horizontal",
|
|
12397
12790
|
position: legendPosition,
|
|
@@ -12424,52 +12817,60 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
12424
12817
|
const height = width / 2;
|
|
12425
12818
|
const radius = height;
|
|
12426
12819
|
const innerRadius = radius * (1 - thickness);
|
|
12820
|
+
const path = (0, _visx_shape.arc)({
|
|
12821
|
+
innerRadius,
|
|
12822
|
+
outerRadius: radius,
|
|
12823
|
+
cornerRadius: 3
|
|
12824
|
+
});
|
|
12427
12825
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Center, {
|
|
12428
|
-
ref:
|
|
12826
|
+
ref: chartRef,
|
|
12429
12827
|
className: pie_semi_circle_chart_module_default["pie-semi-circle-chart__plot"],
|
|
12828
|
+
...chartProps,
|
|
12829
|
+
"aria-label": ariaLabel ?? (0, _wordpress_i18n.__)("Semi-circle chart", "jetpack-charts"),
|
|
12430
12830
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
12831
|
+
ref: svgRef,
|
|
12431
12832
|
width,
|
|
12432
12833
|
height,
|
|
12433
12834
|
viewBox: `0 0 ${width} ${height}`,
|
|
12434
|
-
children: [
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
|
|
12454
|
-
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
|
|
12459
|
-
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
|
|
12464
|
-
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
|
|
12472
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_group.Group, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_text.Text, {
|
|
12835
|
+
children: [
|
|
12836
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RadialWipeAnimation, {
|
|
12837
|
+
id: `radial-wipe-${chartId}`,
|
|
12838
|
+
radius,
|
|
12839
|
+
innerRadius,
|
|
12840
|
+
startAngle: "-180deg",
|
|
12841
|
+
wipePercentage: 50
|
|
12842
|
+
}) }),
|
|
12843
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_group.Group, {
|
|
12844
|
+
top: height,
|
|
12845
|
+
left: width / 2,
|
|
12846
|
+
mask: wipeMask,
|
|
12847
|
+
children: allSegmentsHidden ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SvgEmptyState, {
|
|
12848
|
+
x: 0,
|
|
12849
|
+
y: -radius / 2,
|
|
12850
|
+
width,
|
|
12851
|
+
height,
|
|
12852
|
+
children: getAllHiddenMessage(legendInteractive, "segments")
|
|
12853
|
+
}) : arcs.map((arcDatum) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("g", {
|
|
12854
|
+
...getSegmentHandlers(arcDatum.data, navigationArcs.indexOf(arcDatum)),
|
|
12855
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
12856
|
+
d: path(arcDatum) || "",
|
|
12857
|
+
fill: accessors.fill(arcDatum.data)
|
|
12858
|
+
})
|
|
12859
|
+
}, arcDatum.data.label))
|
|
12860
|
+
}),
|
|
12861
|
+
selectedArc && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_group.Group, {
|
|
12862
|
+
top: height,
|
|
12863
|
+
left: width / 2,
|
|
12864
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectedSegmentRing, {
|
|
12865
|
+
chartId,
|
|
12866
|
+
d: path(selectedArc) || ""
|
|
12867
|
+
})
|
|
12868
|
+
}),
|
|
12869
|
+
!allSegmentsHidden && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_group.Group, {
|
|
12870
|
+
top: height,
|
|
12871
|
+
left: width / 2,
|
|
12872
|
+
mask: wipeMask,
|
|
12873
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_visx_group.Group, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_text.Text, {
|
|
12473
12874
|
textAnchor: "middle",
|
|
12474
12875
|
verticalAnchor: "start",
|
|
12475
12876
|
y: -40,
|
|
@@ -12481,18 +12882,13 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
12481
12882
|
y: -20,
|
|
12482
12883
|
className: pie_semi_circle_chart_module_default.note,
|
|
12483
12884
|
children: note
|
|
12484
|
-
})] }),
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12492
|
-
className: standaloneScopeClass,
|
|
12493
|
-
role: "tooltip",
|
|
12494
|
-
children: renderTooltip({ tooltipData })
|
|
12495
|
-
})
|
|
12885
|
+
})] }), svgChildren]
|
|
12886
|
+
})
|
|
12887
|
+
]
|
|
12888
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PieSelectionOutput, {
|
|
12889
|
+
...selectionOutputProps,
|
|
12890
|
+
keyboardTooltipAnchor: selectedArc && getKeyboardTooltipAnchor(width / 2, height, path.centroid(selectedArc)),
|
|
12891
|
+
renderTooltip
|
|
12496
12892
|
})]
|
|
12497
12893
|
});
|
|
12498
12894
|
}
|