@automattic/charts 4.7.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 +30 -0
- package/TOKENS.md +6 -3
- package/dist/index.cjs +834 -321
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +68 -17
- package/dist/index.d.cts +102 -28
- package/dist/index.d.ts +102 -28
- package/dist/index.js +838 -327
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/charts/area-chart/area-chart.tsx +7 -4
- package/src/charts/area-chart/test/area-chart.test.tsx +24 -15
- package/src/charts/area-chart/test/tooltip-resolution-branches.test.tsx +1 -1
- 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.module.scss +7 -0
- package/src/charts/bar-chart/bar-chart.tsx +25 -16
- package/src/charts/bar-chart/private/comparison-bars.tsx +1 -0
- package/src/charts/bar-chart/test/bar-chart.test.tsx +106 -62
- 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/conversion-funnel-chart/conversion-funnel-chart.tsx +1 -1
- package/src/charts/conversion-funnel-chart/test/conversion-funnel-chart.test.tsx +9 -0
- package/src/charts/heatmap-chart/heatmap-chart.module.scss +16 -8
- package/src/charts/heatmap-chart/heatmap-chart.tsx +183 -66
- 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-context.ts +2 -2
- package/src/charts/heatmap-chart/private/heatmap-legend.tsx +15 -3
- package/src/charts/heatmap-chart/private/heatmap-scale.ts +74 -0
- package/src/charts/heatmap-chart/private/index.ts +6 -3
- package/src/charts/heatmap-chart/private/use-heatmap-colors.ts +24 -6
- 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 +231 -8
- package/src/charts/heatmap-chart/test/heatmap-scale.test.ts +78 -0
- package/src/charts/heatmap-chart/test/use-heatmap-colors.test.ts +18 -6
- package/src/charts/heatmap-chart/types.ts +6 -3
- 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 +7 -4
- 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 +153 -143
- package/src/charts/pie-chart/test/pie-chart.test.tsx +171 -0
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +126 -124
- package/src/charts/pie-semi-circle-chart/test/pie-semi-circle-chart.test.tsx +55 -1
- 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/test/label-text-color.test.ts +6 -8
- package/src/charts/private/x-zoom/test/x-zoom.test.tsx +3 -2
- package/src/components/tooltip/base-tooltip.tsx +31 -32
- package/src/components/tooltip/index.ts +3 -1
- package/src/components/tooltip/private/bounded-tooltip.tsx +15 -15
- package/src/components/tooltip/private/label-value-content.tsx +8 -0
- package/src/components/tooltip/private/xy-chart-tooltip-overlay.tsx +336 -0
- package/src/components/tooltip/test/tool-tip.test.tsx +8 -6
- package/src/components/tooltip/test/tooltip-box.test.tsx +53 -0
- package/src/components/tooltip/test/xy-chart-tooltip-overlay.test.tsx +445 -0
- package/src/components/tooltip/test/xy-chart-tooltip.test.tsx +283 -365
- package/src/components/tooltip/{base-tooltip.module.scss → tooltip-box.module.scss} +5 -8
- package/src/components/tooltip/tooltip-box.tsx +43 -0
- package/src/components/tooltip/types.ts +7 -1
- package/src/components/tooltip/xy-chart-tooltip.tsx +410 -300
- package/src/hooks/test/use-chart-margin.test.tsx +8 -4
- package/src/hooks/use-chart-margin.tsx +21 -18
- package/src/index.ts +8 -3
- package/src/providers/chart-context/global-charts-provider.tsx +5 -14
- package/src/providers/chart-context/hooks/use-default-hidden-series.ts +1 -1
- package/src/providers/chart-context/private/catalog-pointers.ts +1 -0
- package/src/providers/chart-context/private/resolve-opaque-hex.ts +16 -0
- package/src/providers/chart-context/test/use-default-hidden-series.test.tsx +1 -1
- package/src/styles/chart-scope.scss +1 -0
- package/src/test-utils/zoned-parsing-suite.ts +0 -10
- package/src/types.ts +18 -2
- package/src/utils/test/date-formatting.test.ts +0 -10
- package/src/components/tooltip/accessible-tooltip.tsx +0 -433
- package/src/components/tooltip/test/accessible-tooltip.test.tsx +0 -331
package/dist/index.js
CHANGED
|
@@ -4,20 +4,20 @@ 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";
|
|
8
|
-
import { color, hsl } from "@visx/vendor/d3-color";
|
|
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";
|
|
9
8
|
import { differenceInHours, differenceInYears, isValid, parse, parseISO } from "date-fns";
|
|
10
9
|
import { tzOffset } from "@date-fns/tz";
|
|
11
10
|
import { Text, getStringWidth } from "@visx/text";
|
|
12
11
|
import deepmerge from "deepmerge";
|
|
12
|
+
import { color, hsl } from "@visx/vendor/d3-color";
|
|
13
13
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
-
import {
|
|
14
|
+
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;
|
|
@@ -834,6 +834,7 @@ const CATALOG_POINTERS = {
|
|
|
834
834
|
annotation: "var(--a8c-charts-color-annotation, #1e1e1e)",
|
|
835
835
|
surface: "var(--a8c-charts-color-surface, #fff)",
|
|
836
836
|
surfaceSecondary: "var(--a8c-charts-color-surface-secondary, #f4f4f4)",
|
|
837
|
+
track: "var(--a8c-charts-color-track, #f0f0f0)",
|
|
837
838
|
trendUp: "var(--a8c-charts-color-trend-up, #008030)",
|
|
838
839
|
trendDown: "var(--a8c-charts-color-trend-down, #cc1818)",
|
|
839
840
|
series: SERIES_PALETTE_POINTERS
|
|
@@ -1063,6 +1064,15 @@ const rgbLuminance = (rgb) => {
|
|
|
1063
1064
|
* @return Ratio from 1 to 21.
|
|
1064
1065
|
*/
|
|
1065
1066
|
const luminanceContrastRatio = (first, second) => (Math.max(first, second) + .05) / (Math.min(first, second) + .05);
|
|
1067
|
+
/**
|
|
1068
|
+
* WCAG contrast ratio between two hex colors.
|
|
1069
|
+
*
|
|
1070
|
+
* @param first - First hex color.
|
|
1071
|
+
* @param second - Second hex color.
|
|
1072
|
+
* @return Ratio from 1 to 21.
|
|
1073
|
+
* @throws {Error} if either hex string is malformed
|
|
1074
|
+
*/
|
|
1075
|
+
const contrastRatio = (first, second) => luminanceContrastRatio(relativeLuminance(first), relativeLuminance(second));
|
|
1066
1076
|
/** WCAG 1.4.3 text contrast, which a label drawn on a fill needs from at least one label color. */
|
|
1067
1077
|
const MIN_LABEL_CONTRAST = 4.5;
|
|
1068
1078
|
/** Degrees of hue one unit of OKLCH chroma is worth when ranking candidates by hue. */
|
|
@@ -1253,6 +1263,14 @@ const buildPaletteGenerator = (normalizedSeeds, background, labelColors) => {
|
|
|
1253
1263
|
};
|
|
1254
1264
|
};
|
|
1255
1265
|
//#endregion
|
|
1266
|
+
//#region src/providers/chart-context/private/resolve-opaque-hex.ts
|
|
1267
|
+
const resolveOpaqueHex = (pointer, resolve) => {
|
|
1268
|
+
const raw = resolve(pointer);
|
|
1269
|
+
if (!raw || color(raw)?.opacity !== 1) return null;
|
|
1270
|
+
const hex = normalizeColorToHex(raw);
|
|
1271
|
+
return isValidHexColor(hex) ? hex : null;
|
|
1272
|
+
};
|
|
1273
|
+
//#endregion
|
|
1256
1274
|
//#region src/providers/chart-context/themes.ts
|
|
1257
1275
|
/**
|
|
1258
1276
|
* Default theme configuration: the shape and spacing a consumer can override.
|
|
@@ -1301,12 +1319,6 @@ const defaultTheme = {
|
|
|
1301
1319
|
};
|
|
1302
1320
|
//#endregion
|
|
1303
1321
|
//#region src/providers/chart-context/global-charts-provider.tsx
|
|
1304
|
-
const resolveOpaqueHex = (pointer, element) => {
|
|
1305
|
-
const raw = resolveCssVariable(pointer, element);
|
|
1306
|
-
if (!raw || color(raw)?.opacity !== 1) return null;
|
|
1307
|
-
const hex = normalizeColorToHex(pointer, element, resolveCssVariable);
|
|
1308
|
-
return isValidHexColor(hex) ? hex : null;
|
|
1309
|
-
};
|
|
1310
1322
|
const PLACEHOLDER_LABEL_COLORS = [LABEL_FALLBACK, LABEL_INVERSE_FALLBACK];
|
|
1311
1323
|
const GlobalChartsContext = createContext(null);
|
|
1312
1324
|
const GlobalChartsProvider = ({ children, theme, locale, timeZone }) => {
|
|
@@ -1334,8 +1346,9 @@ const GlobalChartsProvider = ({ children, theme, locale, timeZone }) => {
|
|
|
1334
1346
|
const normalizedColor = normalizeColorToHex(color, wrapperRef.current, resolveCssVariable);
|
|
1335
1347
|
if (isValidHexColor(normalizedColor)) resolvedColors.push(normalizedColor);
|
|
1336
1348
|
}
|
|
1337
|
-
const
|
|
1338
|
-
const
|
|
1349
|
+
const resolveAtWrapper = createCssVariableResolver(wrapperRef.current);
|
|
1350
|
+
const backgroundHex = resolveOpaqueHex(CATALOG_POINTERS.background, resolveAtWrapper) ?? "#ffffff";
|
|
1351
|
+
const labelColors = [CATALOG_POINTERS.label, CATALOG_POINTERS.labelInverse].map((pointer) => resolveOpaqueHex(pointer, resolveAtWrapper)).filter((hex) => hex !== null);
|
|
1339
1352
|
setColorCache({
|
|
1340
1353
|
colors: resolvedColors,
|
|
1341
1354
|
background: backgroundHex,
|
|
@@ -1671,10 +1684,10 @@ const DEFAULT_MARGIN_BOTTOM = 20;
|
|
|
1671
1684
|
*/
|
|
1672
1685
|
const DEFAULT_MARGIN_LEFT = 20;
|
|
1673
1686
|
/**
|
|
1674
|
-
* Bottom margin
|
|
1687
|
+
* Bottom margin when no X-axis sits below the chart, because it is on top or hidden.
|
|
1675
1688
|
* We only need a small buffer below the chart in that case.
|
|
1676
1689
|
*/
|
|
1677
|
-
const
|
|
1690
|
+
const DEFAULT_BOTTOM_WITHOUT_X_AXIS = 10;
|
|
1678
1691
|
/**
|
|
1679
1692
|
* Fallback font size used when we cannot derive a font size
|
|
1680
1693
|
* from the theme or axis styles for X-axis tick labels.
|
|
@@ -1754,18 +1767,18 @@ const useChartMargin = (height, options, data, theme, horizontal = false) => {
|
|
|
1754
1767
|
if (yAxisOrientation === "right") defaultMargin.right = yMarginValue;
|
|
1755
1768
|
else defaultMargin.left = yMarginValue;
|
|
1756
1769
|
}
|
|
1757
|
-
const xOrientation = options.axis?.x?.orientation === "top" ? "top" : "bottom";
|
|
1758
|
-
const { fontSize, tickLength, tickLabelStyle } = getXAxisLabelMetrics(theme, xOrientation);
|
|
1759
|
-
const computedXMargin = fontSize + tickLength;
|
|
1760
|
-
if (xOrientation === "top") {
|
|
1761
|
-
defaultMargin.top = Math.max(defaultMargin.top, computedXMargin);
|
|
1762
|
-
defaultMargin.bottom = DEFAULT_BOTTOM_FOR_TOP_AXIS;
|
|
1763
|
-
} else defaultMargin.bottom = Math.max(defaultMargin.bottom, computedXMargin);
|
|
1764
1770
|
if (options.axis?.x?.display !== false) {
|
|
1771
|
+
const xOrientation = options.axis?.x?.orientation === "top" ? "top" : "bottom";
|
|
1772
|
+
const { fontSize, tickLength, tickLabelStyle } = getXAxisLabelMetrics(theme, xOrientation);
|
|
1773
|
+
const computedXMargin = fontSize + tickLength;
|
|
1774
|
+
if (xOrientation === "top") {
|
|
1775
|
+
defaultMargin.top = Math.max(defaultMargin.top, computedXMargin);
|
|
1776
|
+
defaultMargin.bottom = DEFAULT_BOTTOM_WITHOUT_X_AXIS;
|
|
1777
|
+
} else defaultMargin.bottom = Math.max(defaultMargin.bottom, computedXMargin);
|
|
1765
1778
|
const { first, last } = getEdgeTickWidths(options.axis?.x?.tickValues ?? [], options.axis?.x?.tickFormat, tickLabelStyle);
|
|
1766
1779
|
defaultMargin.left = Math.max(defaultMargin.left, Math.ceil(first / 2));
|
|
1767
1780
|
defaultMargin.right = Math.max(defaultMargin.right, Math.ceil(last / 2));
|
|
1768
|
-
}
|
|
1781
|
+
} else defaultMargin.bottom = DEFAULT_BOTTOM_WITHOUT_X_AXIS;
|
|
1769
1782
|
return defaultMargin;
|
|
1770
1783
|
}, [
|
|
1771
1784
|
options,
|
|
@@ -2477,11 +2490,12 @@ function useChartLegendItems(data, options = {}, legendShape) {
|
|
|
2477
2490
|
]);
|
|
2478
2491
|
}
|
|
2479
2492
|
//#endregion
|
|
2480
|
-
//#region src/components/tooltip/
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
"
|
|
2484
|
-
|
|
2493
|
+
//#region src/components/tooltip/private/label-value-content.tsx
|
|
2494
|
+
const LabelValueContent = ({ data }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2495
|
+
data.label,
|
|
2496
|
+
": ",
|
|
2497
|
+
data.valueDisplay || formatNumber(data.value)
|
|
2498
|
+
] });
|
|
2485
2499
|
//#endregion
|
|
2486
2500
|
//#region src/components/tooltip/private/tooltip-theme.tsx
|
|
2487
2501
|
const DEFAULT_SURFACE = "#1e1e1e";
|
|
@@ -2507,28 +2521,63 @@ const TooltipTheme = ({ children }) => {
|
|
|
2507
2521
|
});
|
|
2508
2522
|
};
|
|
2509
2523
|
//#endregion
|
|
2524
|
+
//#region src/components/tooltip/tooltip-box.module.scss
|
|
2525
|
+
var tooltip_box_module_default = { "surface": "a8ccharts-ddpU1W-surface" };
|
|
2526
|
+
//#endregion
|
|
2527
|
+
//#region src/components/tooltip/tooltip-box.tsx
|
|
2528
|
+
/**
|
|
2529
|
+
* The chart tooltip box: the dark surface every chart tooltip draws. It does not position itself; place it with `style` or a wrapper.
|
|
2530
|
+
*
|
|
2531
|
+
* @param props - Div attributes, plus `unstyled`.
|
|
2532
|
+
* @param props.unstyled - Drop the surface, scope class and theme.
|
|
2533
|
+
* @param ref - Forwarded to the box element.
|
|
2534
|
+
* @return The tooltip box.
|
|
2535
|
+
*/
|
|
2536
|
+
const TooltipBox = forwardRef(({ unstyled = false, role = "tooltip", className, children, ...rest }, ref) => {
|
|
2537
|
+
const box = /* @__PURE__ */ jsx("div", {
|
|
2538
|
+
ref,
|
|
2539
|
+
role,
|
|
2540
|
+
className: clsx("visx-tooltip", !unstyled && ["a8c-charts-tooltip-scope", tooltip_box_module_default.surface], className),
|
|
2541
|
+
...rest,
|
|
2542
|
+
children
|
|
2543
|
+
});
|
|
2544
|
+
return unstyled ? box : /* @__PURE__ */ jsx(TooltipTheme, { children: box });
|
|
2545
|
+
});
|
|
2546
|
+
TooltipBox.displayName = "TooltipBox";
|
|
2547
|
+
//#endregion
|
|
2510
2548
|
//#region src/components/tooltip/base-tooltip.tsx
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2549
|
+
/**
|
|
2550
|
+
* A tooltip box with children or `label: value` content. Prefer `TooltipBox`.
|
|
2551
|
+
*
|
|
2552
|
+
* @param props - Tooltip props.
|
|
2553
|
+
* @param props.data - Data for the default content.
|
|
2554
|
+
* @param props.top - Deprecated vertical position.
|
|
2555
|
+
* @param props.left - Deprecated horizontal position.
|
|
2556
|
+
* @param props.component - Deprecated content component.
|
|
2557
|
+
* @param props.children - Tooltip content.
|
|
2558
|
+
* @param props.className - Class name passed to the content component.
|
|
2559
|
+
* @param props.style - Styles for the box.
|
|
2560
|
+
* @param props.renderContainer - Deprecated; render the content alone when false.
|
|
2561
|
+
* @return The tooltip.
|
|
2562
|
+
*/
|
|
2563
|
+
const BaseTooltip = ({ data, top, left, component: Component = LabelValueContent, children, className, style, renderContainer = true }) => {
|
|
2517
2564
|
const content = children || data && /* @__PURE__ */ jsx(Component, {
|
|
2518
2565
|
data,
|
|
2519
2566
|
className
|
|
2520
2567
|
});
|
|
2521
2568
|
if (!renderContainer) return content;
|
|
2522
|
-
return /* @__PURE__ */ jsx(
|
|
2523
|
-
className: clsx(CHART_SCOPE_CLASS, base_tooltip_module_default.tooltip),
|
|
2569
|
+
return /* @__PURE__ */ jsx(TooltipBox, {
|
|
2524
2570
|
style: {
|
|
2525
|
-
top
|
|
2526
|
-
|
|
2571
|
+
...top === void 0 && left === void 0 ? void 0 : {
|
|
2572
|
+
position: "absolute",
|
|
2573
|
+
top,
|
|
2574
|
+
left,
|
|
2575
|
+
transform: "translate(-50%, -100%)"
|
|
2576
|
+
},
|
|
2527
2577
|
...style
|
|
2528
2578
|
},
|
|
2529
|
-
role: "tooltip",
|
|
2530
2579
|
children: content
|
|
2531
|
-
})
|
|
2580
|
+
});
|
|
2532
2581
|
};
|
|
2533
2582
|
//#endregion
|
|
2534
2583
|
//#region src/components/tooltip/private/bounded-tooltip.tsx
|
|
@@ -2608,7 +2657,7 @@ const getBoundedPosition = ({ left, top, offsetLeft, offsetTop, box, wrapper, bo
|
|
|
2608
2657
|
};
|
|
2609
2658
|
};
|
|
2610
2659
|
/**
|
|
2611
|
-
*
|
|
2660
|
+
* A `TooltipBox`, positioned like visx's `TooltipWithBounds` but kept inside the
|
|
2612
2661
|
* nearest clipping ancestor — or the viewport when there is none — rather than
|
|
2613
2662
|
* inside its own parent. Rendered in-tree, a tooltip's parent is the chart
|
|
2614
2663
|
* wrapper, which is often narrower than the box; measuring against the parent
|
|
@@ -2617,7 +2666,7 @@ const getBoundedPosition = ({ left, top, offsetLeft, offsetTop, box, wrapper, bo
|
|
|
2617
2666
|
* Re-measures on every render, so a box whose content changes width between
|
|
2618
2667
|
* two hovers is placed for its current size.
|
|
2619
2668
|
*
|
|
2620
|
-
* @param props -
|
|
2669
|
+
* @param props - `TooltipBox` props plus placement.
|
|
2621
2670
|
* @param props.left - Anchor x, in wrapper coordinates.
|
|
2622
2671
|
* @param props.top - Anchor y, in wrapper coordinates.
|
|
2623
2672
|
* @param props.offsetLeft - Gap between the anchor and the box, horizontally.
|
|
@@ -2683,9 +2732,11 @@ const BoundedTooltip = ({ left = 0, top = 0, offsetLeft = DEFAULT_OFFSET, offset
|
|
|
2683
2732
|
]);
|
|
2684
2733
|
const x = position?.x ?? left + offsetLeft;
|
|
2685
2734
|
const y = position?.y ?? top + (placement === "below-axis" ? POINTER_HEIGHT : offsetTop);
|
|
2686
|
-
|
|
2735
|
+
return /* @__PURE__ */ jsxs(TooltipBox, {
|
|
2687
2736
|
ref: nodeRef,
|
|
2688
|
-
|
|
2737
|
+
role: "presentation",
|
|
2738
|
+
unstyled,
|
|
2739
|
+
className,
|
|
2689
2740
|
style: {
|
|
2690
2741
|
position: "absolute",
|
|
2691
2742
|
left: 0,
|
|
@@ -2708,10 +2759,9 @@ const BoundedTooltip = ({ left = 0, top = 0, offsetLeft = DEFAULT_OFFSET, offset
|
|
|
2708
2759
|
}
|
|
2709
2760
|
}), children]
|
|
2710
2761
|
});
|
|
2711
|
-
return unstyled ? box : /* @__PURE__ */ jsx(TooltipTheme, { children: box });
|
|
2712
2762
|
};
|
|
2713
2763
|
//#endregion
|
|
2714
|
-
//#region src/components/tooltip/xy-chart-tooltip.tsx
|
|
2764
|
+
//#region src/components/tooltip/private/xy-chart-tooltip-overlay.tsx
|
|
2715
2765
|
const CROSSHAIR_STROKE_WIDTH = 1.5;
|
|
2716
2766
|
const CROSSHAIR_PAINT_PROPERTIES = /* @__PURE__ */ new Set([
|
|
2717
2767
|
"stroke",
|
|
@@ -2813,21 +2863,35 @@ const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, rende
|
|
|
2813
2863
|
const crosshairStroke = theme?.gridStyles?.stroke ?? theme?.htmlLabel?.color ?? FALLBACK_COLOR;
|
|
2814
2864
|
const marginTop = margin?.top ?? 0;
|
|
2815
2865
|
const marginLeft = margin?.left ?? 0;
|
|
2816
|
-
const TooltipComponent = detectBounds || tooltipPlacement !== "auto" ? BoundedTooltip : Tooltip;
|
|
2817
2866
|
const boxStyle = {
|
|
2818
2867
|
zIndex,
|
|
2819
2868
|
...style
|
|
2820
2869
|
};
|
|
2821
|
-
const
|
|
2822
|
-
const
|
|
2870
|
+
const { offsetLeft = 10, offsetTop = 10, unstyled, className, ...boxProps } = tooltipProps;
|
|
2871
|
+
const anchorTop = tooltipPlacement === "below-axis" ? marginTop + innerHeight + (margin?.bottom ?? 0) : tooltipAnchorTop ?? tooltipTop;
|
|
2872
|
+
const box = detectBounds || tooltipPlacement !== "auto" ? /* @__PURE__ */ jsx(BoundedTooltip, {
|
|
2823
2873
|
left: tooltipLeft,
|
|
2824
|
-
top:
|
|
2874
|
+
top: anchorTop,
|
|
2875
|
+
offsetLeft,
|
|
2876
|
+
offsetTop,
|
|
2877
|
+
unstyled,
|
|
2878
|
+
className,
|
|
2825
2879
|
style: boxStyle,
|
|
2826
|
-
|
|
2827
|
-
...tooltipProps,
|
|
2828
|
-
className: clsx(themesOwnBox && ["a8c-charts-scope", base_tooltip_module_default.surface], tooltipProps.className),
|
|
2880
|
+
...boxProps,
|
|
2829
2881
|
...tooltipPlacement !== "auto" && { placement: tooltipPlacement },
|
|
2830
2882
|
children: tooltipContent
|
|
2883
|
+
}) : /* @__PURE__ */ jsx(TooltipBox, {
|
|
2884
|
+
role: "presentation",
|
|
2885
|
+
unstyled,
|
|
2886
|
+
className,
|
|
2887
|
+
style: {
|
|
2888
|
+
position: "absolute",
|
|
2889
|
+
left: (tooltipLeft ?? 0) + offsetLeft,
|
|
2890
|
+
top: (anchorTop ?? 0) + offsetTop,
|
|
2891
|
+
...!unstyled && boxStyle
|
|
2892
|
+
},
|
|
2893
|
+
...boxProps,
|
|
2894
|
+
children: tooltipContent
|
|
2831
2895
|
});
|
|
2832
2896
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("g", {
|
|
2833
2897
|
className: "visx-tooltip-overlay",
|
|
@@ -2855,7 +2919,7 @@ const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, rende
|
|
|
2855
2919
|
}),
|
|
2856
2920
|
glyphs
|
|
2857
2921
|
]
|
|
2858
|
-
}), container && createPortal(
|
|
2922
|
+
}), container && createPortal(box, container)] });
|
|
2859
2923
|
};
|
|
2860
2924
|
/**
|
|
2861
2925
|
* In-tree replacement for `@visx/xychart`'s `Tooltip`.
|
|
@@ -2880,7 +2944,7 @@ const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, rende
|
|
|
2880
2944
|
* @param props - visx's `Tooltip` options. `scroll`, `debounce` and `resizeObserverPolyfill` are accepted and ignored.
|
|
2881
2945
|
* @return An anchor in the SVG, plus the overlay and the tooltip box while the tooltip is open.
|
|
2882
2946
|
*/
|
|
2883
|
-
const
|
|
2947
|
+
const XyChartTooltipOverlay = (props) => {
|
|
2884
2948
|
const tooltipContext = useContext(TooltipContext);
|
|
2885
2949
|
const [container, setContainer] = useState(null);
|
|
2886
2950
|
const anchorRef = useCallback((node) => {
|
|
@@ -2893,8 +2957,8 @@ const XyChartTooltip = (props) => {
|
|
|
2893
2957
|
})] });
|
|
2894
2958
|
};
|
|
2895
2959
|
//#endregion
|
|
2896
|
-
//#region src/components/tooltip/
|
|
2897
|
-
const
|
|
2960
|
+
//#region src/components/tooltip/xy-chart-tooltip.tsx
|
|
2961
|
+
const XYChartTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocusedClassName, series = [], mode = "group", verticalCrosshairStyle, horizontalCrosshairStyle, ...props }) => {
|
|
2898
2962
|
const tooltipContext = useContext(TooltipContext);
|
|
2899
2963
|
const scopeElement = useChartScopeElement();
|
|
2900
2964
|
const crosshairStroke = useMemo(() => {
|
|
@@ -3000,7 +3064,7 @@ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardF
|
|
|
3000
3064
|
keyboardFocusedClassName,
|
|
3001
3065
|
standaloneScopeClass
|
|
3002
3066
|
]);
|
|
3003
|
-
return /* @__PURE__ */ jsx(
|
|
3067
|
+
return /* @__PURE__ */ jsx(XyChartTooltipOverlay, {
|
|
3004
3068
|
...props,
|
|
3005
3069
|
verticalCrosshairStyle: {
|
|
3006
3070
|
...crosshairStroke,
|
|
@@ -3013,8 +3077,10 @@ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardF
|
|
|
3013
3077
|
renderTooltip: focusableRenderTooltip
|
|
3014
3078
|
});
|
|
3015
3079
|
};
|
|
3080
|
+
/** @deprecated Use `XYChartTooltip`. */
|
|
3081
|
+
const AccessibleTooltip = XYChartTooltip;
|
|
3016
3082
|
const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating, setIsNavigating, chartRef, totalPoints, onActivate, preventTooltipScroll = false, visibleSeriesKey }) => {
|
|
3017
|
-
const getChartRoot = useCallback(() => chartRef.current?.closest("[role=\"
|
|
3083
|
+
const getChartRoot = useCallback(() => chartRef.current?.closest("[role=\"application\"]") ?? chartRef.current, [chartRef]);
|
|
3018
3084
|
const focusWithoutScrollIfNeeded = useCallback((element) => {
|
|
3019
3085
|
if (preventTooltipScroll) element?.focus({ preventScroll: true });
|
|
3020
3086
|
else element?.focus();
|
|
@@ -3229,11 +3295,13 @@ function useChartChildren(children, chartType) {
|
|
|
3229
3295
|
}
|
|
3230
3296
|
const displayName = child.type?.displayName;
|
|
3231
3297
|
if (displayName === `${chartType}.SVG` || displayName === "Chart.SVG") {
|
|
3232
|
-
|
|
3298
|
+
const { children: svgChildren } = child.props ?? {};
|
|
3299
|
+
if (svgChildren) Children.forEach(svgChildren, (svgChild) => {
|
|
3233
3300
|
svg.push(svgChild);
|
|
3234
3301
|
});
|
|
3235
3302
|
} else if (displayName === `${chartType}.HTML` || displayName === "Chart.HTML") {
|
|
3236
|
-
|
|
3303
|
+
const { children: htmlChildren } = child.props ?? {};
|
|
3304
|
+
if (htmlChildren) Children.forEach(htmlChildren, (htmlChild) => {
|
|
3237
3305
|
html.push(htmlChild);
|
|
3238
3306
|
});
|
|
3239
3307
|
} else if (child.type === Group) svg.push(child);
|
|
@@ -4055,6 +4123,7 @@ var line_chart_module_default = {
|
|
|
4055
4123
|
"line-chart--animated": "a8ccharts-inuQka-line-chart--animated",
|
|
4056
4124
|
"rise": "a8ccharts-inuQka-rise"
|
|
4057
4125
|
};
|
|
4126
|
+
const isReact18 = version.startsWith("18.");
|
|
4058
4127
|
const CloseIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
4059
4128
|
width: "16",
|
|
4060
4129
|
height: "16",
|
|
@@ -4097,7 +4166,7 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
|
|
|
4097
4166
|
className: line_chart_module_default["line-chart__annotation-label"],
|
|
4098
4167
|
children: [/* @__PURE__ */ jsx("button", {
|
|
4099
4168
|
ref: buttonRef,
|
|
4100
|
-
popovertarget: popoverId,
|
|
4169
|
+
...isReact18 ? { popovertarget: popoverId } : { popoverTarget: popoverId },
|
|
4101
4170
|
className: line_chart_module_default["line-chart__annotation-label-trigger-button"],
|
|
4102
4171
|
style: {
|
|
4103
4172
|
width: `44px`,
|
|
@@ -4125,8 +4194,13 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
|
|
|
4125
4194
|
subtitle
|
|
4126
4195
|
})
|
|
4127
4196
|
}), /* @__PURE__ */ jsx("button", {
|
|
4128
|
-
|
|
4129
|
-
|
|
4197
|
+
...isReact18 ? {
|
|
4198
|
+
popovertarget: popoverId,
|
|
4199
|
+
popovertargetaction: "hide"
|
|
4200
|
+
} : {
|
|
4201
|
+
popoverTarget: popoverId,
|
|
4202
|
+
popoverTargetAction: "hide"
|
|
4203
|
+
},
|
|
4130
4204
|
className: line_chart_module_default["line-chart__annotation-label-popover-close-button"],
|
|
4131
4205
|
"aria-label": __("Close", "jetpack-charts"),
|
|
4132
4206
|
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
@@ -4648,7 +4722,7 @@ const LineChartScalesRef = ({ chartRef, width, height, margin }) => {
|
|
|
4648
4722
|
]);
|
|
4649
4723
|
return null;
|
|
4650
4724
|
};
|
|
4651
|
-
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) => {
|
|
4652
4726
|
const legendInteractive = legend.interactive ?? false;
|
|
4653
4727
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
4654
4728
|
const legendComparisonItem = legend.comparisonItem ?? false;
|
|
@@ -4916,8 +4990,8 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4916
4990
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
4917
4991
|
return /* @__PURE__ */ jsx("div", {
|
|
4918
4992
|
ref: chartRef,
|
|
4919
|
-
role: "
|
|
4920
|
-
"aria-label": __("Line chart", "jetpack-charts"),
|
|
4993
|
+
role: "application",
|
|
4994
|
+
"aria-label": ariaLabel ?? __("Line chart", "jetpack-charts"),
|
|
4921
4995
|
tabIndex: 0,
|
|
4922
4996
|
onKeyDown: onChartKeyDown,
|
|
4923
4997
|
onFocus: onChartFocus,
|
|
@@ -4925,6 +4999,7 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
4925
4999
|
children: chartHeight > 0 && /* @__PURE__ */ jsxs("div", {
|
|
4926
5000
|
className: xy_plot_module_default["xy-plot"],
|
|
4927
5001
|
children: [zoomable && zoom.domain && /* @__PURE__ */ jsx(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ jsxs(XYChart, {
|
|
5002
|
+
accessibilityLabel: "",
|
|
4928
5003
|
theme,
|
|
4929
5004
|
width,
|
|
4930
5005
|
height: chartHeight,
|
|
@@ -5018,7 +5093,7 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
5018
5093
|
] }, seriesData?.label || index);
|
|
5019
5094
|
})
|
|
5020
5095
|
}),
|
|
5021
|
-
withTooltips && /* @__PURE__ */ jsx(
|
|
5096
|
+
withTooltips && /* @__PURE__ */ jsx(XYChartTooltip, {
|
|
5022
5097
|
detectBounds: true,
|
|
5023
5098
|
snapTooltipToDatumX: true,
|
|
5024
5099
|
tooltipPlacement,
|
|
@@ -5165,7 +5240,7 @@ const HoverGlyphs = ({ visibleSeries, stacked, stackOffset, getElementStyles, st
|
|
|
5165
5240
|
};
|
|
5166
5241
|
//#endregion
|
|
5167
5242
|
//#region src/charts/area-chart/area-chart.tsx
|
|
5168
|
-
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) => {
|
|
5169
5244
|
const legendInteractive = legend.interactive ?? false;
|
|
5170
5245
|
const legendShape = legend.shape ?? "rect";
|
|
5171
5246
|
const legendPosition = legend.position ?? "bottom";
|
|
@@ -5436,8 +5511,8 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
5436
5511
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
5437
5512
|
return /* @__PURE__ */ jsx("div", {
|
|
5438
5513
|
ref: chartRef,
|
|
5439
|
-
role: "
|
|
5440
|
-
"aria-label": __("Area chart", "jetpack-charts"),
|
|
5514
|
+
role: "application",
|
|
5515
|
+
"aria-label": ariaLabel ?? __("Area chart", "jetpack-charts"),
|
|
5441
5516
|
tabIndex: 0,
|
|
5442
5517
|
onKeyDown: onChartKeyDown,
|
|
5443
5518
|
onFocus: onChartFocus,
|
|
@@ -5445,6 +5520,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
5445
5520
|
children: chartHeight > 0 && /* @__PURE__ */ jsxs("div", {
|
|
5446
5521
|
className: xy_plot_module_default["xy-plot"],
|
|
5447
5522
|
children: [zoomable && zoom.domain && /* @__PURE__ */ jsx(ZoomResetButton, { onClick: zoom.reset }), /* @__PURE__ */ jsxs(XYChart, {
|
|
5523
|
+
accessibilityLabel: "",
|
|
5448
5524
|
theme,
|
|
5449
5525
|
width,
|
|
5450
5526
|
height: chartHeight,
|
|
@@ -5494,7 +5570,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
|
|
|
5494
5570
|
children: seriesWithVisibility.map(renderSeries)
|
|
5495
5571
|
}), !allSeriesHidden && !stacked && seriesWithVisibility.map(renderSeries)]
|
|
5496
5572
|
}),
|
|
5497
|
-
withTooltips && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(
|
|
5573
|
+
withTooltips && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(XYChartTooltip, {
|
|
5498
5574
|
detectBounds: true,
|
|
5499
5575
|
snapTooltipToDatumX: true,
|
|
5500
5576
|
snapTooltipToDatumY: !stacked,
|
|
@@ -6105,6 +6181,7 @@ const ComparisonBars = ({ comparisonEntries, primaryKeys, groupPadding, horizont
|
|
|
6105
6181
|
widthFactor
|
|
6106
6182
|
});
|
|
6107
6183
|
rects.push(/* @__PURE__ */ jsx("rect", {
|
|
6184
|
+
className: "bar-chart__comparison-bar",
|
|
6108
6185
|
x: rect.x,
|
|
6109
6186
|
y: rect.y,
|
|
6110
6187
|
width: rect.width,
|
|
@@ -6296,7 +6373,7 @@ const renderTooltipRow = (label, value) => /* @__PURE__ */ jsx("div", {
|
|
|
6296
6373
|
className: bar_chart_module_default["bar-chart__tooltip-row"],
|
|
6297
6374
|
children: sprintf(__("%1$s: %2$s", "jetpack-charts"), label, value)
|
|
6298
6375
|
});
|
|
6299
|
-
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 }) => {
|
|
6300
6377
|
if (!withTooltips && (withBandHighlight || onBandHighlightChange)) warnOnce("bar-chart-band-highlight-without-tooltips", "BarChart: withBandHighlight and onBandHighlightChange require withTooltips.");
|
|
6301
6378
|
const legendInteractive = legend.interactive ?? false;
|
|
6302
6379
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
@@ -6520,7 +6597,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6520
6597
|
const patternId = getPatternId(chartId, index);
|
|
6521
6598
|
return `
|
|
6522
6599
|
.visx-bar[fill="url(#${patternId})"],
|
|
6523
|
-
.bar-chart__comparison-
|
|
6600
|
+
.bar-chart__comparison-bar[fill="url(#${patternId})"] {
|
|
6524
6601
|
stroke: ${color};
|
|
6525
6602
|
stroke-width: 1;
|
|
6526
6603
|
}
|
|
@@ -6604,9 +6681,9 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6604
6681
|
children: ({ contentHeight }) => {
|
|
6605
6682
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
6606
6683
|
return /* @__PURE__ */ jsx("div", {
|
|
6607
|
-
role: "
|
|
6684
|
+
role: "application",
|
|
6608
6685
|
ref: chartRef,
|
|
6609
|
-
"aria-label": __("Bar chart", "jetpack-charts"),
|
|
6686
|
+
"aria-label": ariaLabel ?? __("Bar chart", "jetpack-charts"),
|
|
6610
6687
|
tabIndex: 0,
|
|
6611
6688
|
onKeyDown: onChartKeyDown,
|
|
6612
6689
|
onFocus: onChartFocus,
|
|
@@ -6614,6 +6691,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6614
6691
|
children: chartHeight > 0 && /* @__PURE__ */ jsx("div", {
|
|
6615
6692
|
className: xy_plot_module_default["xy-plot"],
|
|
6616
6693
|
children: /* @__PURE__ */ jsxs(XYChart, {
|
|
6694
|
+
accessibilityLabel: "",
|
|
6617
6695
|
theme,
|
|
6618
6696
|
width,
|
|
6619
6697
|
height: chartHeight,
|
|
@@ -6702,15 +6780,15 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
6702
6780
|
}),
|
|
6703
6781
|
!allSeriesHidden && /* @__PURE__ */ jsx(WholeNumberTicks, {
|
|
6704
6782
|
...wholeNumberTicksProps,
|
|
6705
|
-
children: (valueTicks) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Axis, {
|
|
6783
|
+
children: (valueTicks) => /* @__PURE__ */ jsxs(Fragment$1, { children: [chartOptions.axis.x.display !== false && /* @__PURE__ */ jsx(Axis, {
|
|
6706
6784
|
...chartOptions.axis.x,
|
|
6707
6785
|
...horizontal && valueTicks ? { tickValues: valueTicks } : {}
|
|
6708
|
-
}), /* @__PURE__ */ jsx(Axis, {
|
|
6786
|
+
}), chartOptions.axis.y.display !== false && /* @__PURE__ */ jsx(Axis, {
|
|
6709
6787
|
...chartOptions.axis.y,
|
|
6710
6788
|
...!horizontal && valueTicks ? { tickValues: valueTicks } : {}
|
|
6711
6789
|
})] })
|
|
6712
6790
|
}),
|
|
6713
|
-
withTooltips && /* @__PURE__ */ jsx(
|
|
6791
|
+
withTooltips && /* @__PURE__ */ jsx(XYChartTooltip, {
|
|
6714
6792
|
tooltipPlacement,
|
|
6715
6793
|
tooltipAnchorTop,
|
|
6716
6794
|
style: tooltipStyle,
|
|
@@ -7237,7 +7315,10 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
|
|
|
7237
7315
|
left: tooltipLeft,
|
|
7238
7316
|
className: standaloneScopeClass,
|
|
7239
7317
|
style: tooltipStyle,
|
|
7240
|
-
children:
|
|
7318
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
7319
|
+
role: "tooltip",
|
|
7320
|
+
children: tooltipContent
|
|
7321
|
+
})
|
|
7241
7322
|
});
|
|
7242
7323
|
})()]
|
|
7243
7324
|
});
|
|
@@ -7616,6 +7697,7 @@ var heatmap_chart_module_default = {
|
|
|
7616
7697
|
"heatmap-chart__legend-label": "a8ccharts-O3YMOW-heatmap-chart__legend-label",
|
|
7617
7698
|
"heatmap-chart__legend-scale--bar": "a8ccharts-O3YMOW-heatmap-chart__legend-scale--bar",
|
|
7618
7699
|
"heatmap-chart__legend-swatch": "a8ccharts-O3YMOW-heatmap-chart__legend-swatch",
|
|
7700
|
+
"heatmap-chart__legend-swatch--empty": "a8ccharts-O3YMOW-heatmap-chart__legend-swatch--empty",
|
|
7619
7701
|
"heatmap-chart__row": "a8ccharts-O3YMOW-heatmap-chart__row",
|
|
7620
7702
|
"heatmap-chart__row-label": "a8ccharts-O3YMOW-heatmap-chart__row-label",
|
|
7621
7703
|
"heatmap-chart--height-capped": "a8ccharts-O3YMOW-heatmap-chart--height-capped"
|
|
@@ -7624,30 +7706,44 @@ var heatmap_chart_module_default = {
|
|
|
7624
7706
|
//#region src/charts/heatmap-chart/private/use-heatmap-colors.ts
|
|
7625
7707
|
const isPresent = (value) => value !== null && value !== void 0 && !isNaN(value);
|
|
7626
7708
|
/**
|
|
7627
|
-
* Get the min and max values from heatmap data, ignoring null/NaN
|
|
7628
|
-
* columns stay out: a roll-up on the
|
|
7709
|
+
* Get the min and max values from heatmap data, ignoring null/NaN and the zeros
|
|
7710
|
+
* `isEmptyValue` paints as empty. Summary columns stay out: a roll-up on the
|
|
7711
|
+
* scale would flatten every real cell.
|
|
7629
7712
|
* @param data - The heatmap columns
|
|
7630
7713
|
* @return Tuple of [min, max] values
|
|
7631
7714
|
*/
|
|
7632
7715
|
const getValueExtent = (data) => {
|
|
7633
7716
|
let min = Infinity;
|
|
7634
7717
|
let max = -Infinity;
|
|
7718
|
+
let hasZero = false;
|
|
7635
7719
|
for (const column of data) {
|
|
7636
7720
|
if (column.summary) continue;
|
|
7637
7721
|
for (const cell of column.data) {
|
|
7638
7722
|
if (!isPresent(cell.value)) continue;
|
|
7723
|
+
if (cell.value === 0) {
|
|
7724
|
+
hasZero = true;
|
|
7725
|
+
continue;
|
|
7726
|
+
}
|
|
7639
7727
|
if (cell.value < min) min = cell.value;
|
|
7640
7728
|
if (cell.value > max) max = cell.value;
|
|
7641
7729
|
}
|
|
7642
7730
|
}
|
|
7731
|
+
if (hasZero && min < 0) max = Math.max(max, 0);
|
|
7643
7732
|
if (min === Infinity) return [0, 0];
|
|
7644
7733
|
return [min, max];
|
|
7645
7734
|
};
|
|
7646
7735
|
/**
|
|
7736
|
+
* Whether a value paints as an empty cell: a zero in data with no negatives
|
|
7737
|
+
* counts nothing, so it must not look like the lowest step of activity.
|
|
7738
|
+
*
|
|
7739
|
+
* @param value - The cell value
|
|
7740
|
+
* @param extent - The extent from `getValueExtent`
|
|
7741
|
+
* @return True when the cell takes the empty-cell color
|
|
7742
|
+
*/
|
|
7743
|
+
const isEmptyValue = (value, extent) => value === 0 && extent[0] >= 0;
|
|
7744
|
+
/**
|
|
7647
7745
|
* Normalize a value to 0–1 within the extent. A flat extent (min === max)
|
|
7648
|
-
* maps to 1
|
|
7649
|
-
* extent, which maps to 0 so a no-activity grid renders at the scale's
|
|
7650
|
-
* bottom instead of full intensity.
|
|
7746
|
+
* maps to 1, since every cell is equally the "highest".
|
|
7651
7747
|
*
|
|
7652
7748
|
* @param value - The value to normalize
|
|
7653
7749
|
* @param extent - Tuple of [min, max] values for the normalization range
|
|
@@ -7655,9 +7751,40 @@ const getValueExtent = (data) => {
|
|
|
7655
7751
|
*/
|
|
7656
7752
|
const getNormalizedValue = (value, extent) => {
|
|
7657
7753
|
const [min, max] = extent;
|
|
7658
|
-
if (min === max) return
|
|
7754
|
+
if (min === max) return 1;
|
|
7659
7755
|
return Math.min(1, Math.max(0, (value - min) / (max - min)));
|
|
7660
7756
|
};
|
|
7757
|
+
const STEPS = 200;
|
|
7758
|
+
const firstMeeting = (from, to, meets) => {
|
|
7759
|
+
for (let step = 0; step <= STEPS; step++) {
|
|
7760
|
+
const color = mixHexColors(from, to, step / STEPS);
|
|
7761
|
+
if (meets(color)) return color;
|
|
7762
|
+
}
|
|
7763
|
+
return null;
|
|
7764
|
+
};
|
|
7765
|
+
/**
|
|
7766
|
+
* The two ends of the heatmap fill scale: 3:1 against the background and the empty cell at the
|
|
7767
|
+
* low end, toward 9:1 against the background at the high end.
|
|
7768
|
+
*
|
|
7769
|
+
* @param primary - The resolved primary color, as six-digit hex.
|
|
7770
|
+
* @param background - The resolved chart background, as six-digit hex.
|
|
7771
|
+
* @param emptyCell - The resolved empty-cell color, as six-digit hex, when it is opaque.
|
|
7772
|
+
* @return The scale ends, as six-digit hex.
|
|
7773
|
+
*/
|
|
7774
|
+
const getHeatmapScale = (primary, background, emptyCell) => {
|
|
7775
|
+
const primaryStandsOut = contrastRatio(primary, background) >= 3;
|
|
7776
|
+
const extreme = (primaryStandsOut ? relativeLuminance(primary) > relativeLuminance(background) : contrastRatio("#ffffff", background) > contrastRatio("#000000", background)) ? "#ffffff" : "#000000";
|
|
7777
|
+
const lowAgainst = (references) => {
|
|
7778
|
+
const meets = (color) => references.every((reference) => contrastRatio(color, reference) >= 3);
|
|
7779
|
+
return (primaryStandsOut ? firstMeeting(background, primary, meets) : null) ?? firstMeeting(primary, extreme, meets);
|
|
7780
|
+
};
|
|
7781
|
+
const high = firstMeeting(primary, extreme, (color) => contrastRatio(color, background) >= 9) ?? extreme;
|
|
7782
|
+
const againstEmptyCell = emptyCell ? lowAgainst([background, emptyCell]) : null;
|
|
7783
|
+
return {
|
|
7784
|
+
low: (againstEmptyCell && contrastRatio(againstEmptyCell, background) <= contrastRatio(high, background) ? againstEmptyCell : lowAgainst([background])) ?? extreme,
|
|
7785
|
+
high
|
|
7786
|
+
};
|
|
7787
|
+
};
|
|
7661
7788
|
//#endregion
|
|
7662
7789
|
//#region src/charts/heatmap-chart/private/heatmap-context.ts
|
|
7663
7790
|
/** Shared by the chart and legend without importing back from `heatmap-chart.tsx`. */
|
|
@@ -7668,8 +7795,9 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7668
7795
|
const context = useContext(HeatmapContext);
|
|
7669
7796
|
const { legend } = useGlobalChartsTheme();
|
|
7670
7797
|
if (!context) return null;
|
|
7671
|
-
const {
|
|
7798
|
+
const { extent, fillVars } = context;
|
|
7672
7799
|
const labelStyle = legend.labelStyles;
|
|
7800
|
+
const showsEmptyCell = isEmptyValue(0, extent);
|
|
7673
7801
|
return /* @__PURE__ */ jsxs(Stack, {
|
|
7674
7802
|
direction: "row",
|
|
7675
7803
|
gap: "xs",
|
|
@@ -7681,21 +7809,21 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
|
|
|
7681
7809
|
style: labelStyle,
|
|
7682
7810
|
children: lessLabel ?? __("Less", "jetpack-charts")
|
|
7683
7811
|
}),
|
|
7684
|
-
/* @__PURE__ */
|
|
7812
|
+
/* @__PURE__ */ jsxs(Stack, {
|
|
7685
7813
|
direction: "row",
|
|
7686
7814
|
gap: variant === "bar" ? void 0 : "xs",
|
|
7687
7815
|
"aria-hidden": "true",
|
|
7688
7816
|
className: variant === "bar" ? heatmap_chart_module_default["heatmap-chart__legend-scale--bar"] : void 0,
|
|
7689
|
-
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) => {
|
|
7690
7818
|
const intensity = steps <= 1 ? 1 : index / (steps - 1);
|
|
7691
7819
|
return /* @__PURE__ */ jsx("span", {
|
|
7692
7820
|
className: heatmap_chart_module_default["heatmap-chart__legend-swatch"],
|
|
7693
7821
|
style: {
|
|
7694
|
-
|
|
7822
|
+
...fillVars,
|
|
7695
7823
|
"--a8c-charts-heatmap-cell-intensity": intensity
|
|
7696
7824
|
}
|
|
7697
7825
|
}, index);
|
|
7698
|
-
})
|
|
7826
|
+
})]
|
|
7699
7827
|
}),
|
|
7700
7828
|
/* @__PURE__ */ jsx(Text$1, {
|
|
7701
7829
|
variant: "body-sm",
|
|
@@ -7721,9 +7849,11 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7721
7849
|
const ungrouped = () => ({
|
|
7722
7850
|
columns: Array.from({ length: columnCount }, (_, index) => ({
|
|
7723
7851
|
line: firstLine + index,
|
|
7852
|
+
band: 0,
|
|
7724
7853
|
gapBefore: false
|
|
7725
7854
|
})),
|
|
7726
|
-
groups: []
|
|
7855
|
+
groups: [],
|
|
7856
|
+
bands: 1
|
|
7727
7857
|
});
|
|
7728
7858
|
if (!groups || groups.length === 0 || columnCount === 0) return ungrouped();
|
|
7729
7859
|
const spans = groups.map((group) => group.span);
|
|
@@ -7739,11 +7869,13 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7739
7869
|
if (groupIndex > 0) line += 1;
|
|
7740
7870
|
laidOut.push({
|
|
7741
7871
|
...group,
|
|
7742
|
-
line
|
|
7872
|
+
line,
|
|
7873
|
+
band: 0
|
|
7743
7874
|
});
|
|
7744
7875
|
for (let offset = 0; offset < group.span; offset++) {
|
|
7745
7876
|
columns.push({
|
|
7746
7877
|
line,
|
|
7878
|
+
band: 0,
|
|
7747
7879
|
gapBefore: groupIndex > 0 && offset === 0,
|
|
7748
7880
|
group: groupIndex
|
|
7749
7881
|
});
|
|
@@ -7753,13 +7885,99 @@ const resolveColumnGroups = (groups, columnCount, firstLine) => {
|
|
|
7753
7885
|
while (columns.length < columnCount) {
|
|
7754
7886
|
columns.push({
|
|
7755
7887
|
line,
|
|
7888
|
+
band: 0,
|
|
7756
7889
|
gapBefore: false
|
|
7757
7890
|
});
|
|
7758
7891
|
line += 1;
|
|
7759
7892
|
}
|
|
7760
7893
|
return {
|
|
7761
7894
|
columns,
|
|
7762
|
-
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
|
|
7763
7981
|
};
|
|
7764
7982
|
};
|
|
7765
7983
|
//#endregion
|
|
@@ -7895,7 +8113,6 @@ const stepCalendarCell = (grid, blocks, from, key) => {
|
|
|
7895
8113
|
};
|
|
7896
8114
|
//#endregion
|
|
7897
8115
|
//#region src/charts/heatmap-chart/heatmap-chart.tsx
|
|
7898
|
-
const CELL_MIX_FLOOR = .15;
|
|
7899
8116
|
const CELL_VALUE_MODIFIER = {
|
|
7900
8117
|
label: void 0,
|
|
7901
8118
|
"label-inverse": heatmap_chart_module_default["heatmap-chart__cell-value--inverse"],
|
|
@@ -7904,12 +8121,26 @@ const CELL_VALUE_MODIFIER = {
|
|
|
7904
8121
|
};
|
|
7905
8122
|
const NO_ROW_LABELS = [];
|
|
7906
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
|
+
};
|
|
7907
8138
|
const cellName = (info) => info.cellLabel || [
|
|
7908
8139
|
info.groupLabel,
|
|
7909
8140
|
info.columnLabel,
|
|
7910
8141
|
info.rowLabel
|
|
7911
8142
|
].filter(Boolean).join(" ");
|
|
7912
|
-
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 }) => {
|
|
7913
8144
|
const chartId = useChartId(providedChartId);
|
|
7914
8145
|
const tooltipBoxStyle = tooltipStyle ? {
|
|
7915
8146
|
...TOOLTIP_BOX_STYLE,
|
|
@@ -7923,19 +8154,30 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
7923
8154
|
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, showTooltip, hideTooltip } = useTooltip();
|
|
7924
8155
|
const standaloneScopeClass = useStandaloneScopeClass();
|
|
7925
8156
|
const containerRef = useRef(null);
|
|
8157
|
+
const chartRef = useRef(null);
|
|
7926
8158
|
const [labelRoles, setLabelRoles] = useState(null);
|
|
7927
|
-
const getTooltipOrigin = useCallback(() =>
|
|
8159
|
+
const getTooltipOrigin = useCallback(() => chartRef.current?.getBoundingClientRect() ?? null, []);
|
|
7928
8160
|
const { color: primaryColorHex } = getElementStyles({
|
|
7929
8161
|
index: 0,
|
|
7930
8162
|
overrideColor: primaryColor
|
|
7931
8163
|
});
|
|
7932
|
-
const
|
|
8164
|
+
const resolveAtScope = createCssVariableResolver(scopeElement);
|
|
8165
|
+
const chartBackgroundHex = resolveOpaqueHex(CATALOG_POINTERS.background, resolveAtScope) ?? "#ffffff";
|
|
8166
|
+
const emptyCellHex = resolveOpaqueHex(CATALOG_POINTERS.track, resolveAtScope);
|
|
7933
8167
|
const primaryHex = normalizeColorToHex(primaryColorHex);
|
|
7934
|
-
const
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
8168
|
+
const scale = useMemo(() => isValidHexColor(primaryHex) ? getHeatmapScale(primaryHex, chartBackgroundHex, emptyCellHex) : null, [
|
|
8169
|
+
primaryHex,
|
|
8170
|
+
chartBackgroundHex,
|
|
8171
|
+
emptyCellHex
|
|
8172
|
+
]);
|
|
8173
|
+
const fillVars = useMemo(() => ({
|
|
8174
|
+
"--a8c-charts-color-heatmap-primary": primaryColorHex,
|
|
8175
|
+
...scale && {
|
|
8176
|
+
"--a8c-charts-color-heatmap-low": scale.low,
|
|
8177
|
+
"--a8c-charts-color-heatmap-high": scale.high
|
|
8178
|
+
}
|
|
8179
|
+
}), [primaryColorHex, scale]);
|
|
8180
|
+
const cellTextColor = (intensity) => scale ? pickLabelTextColorForFill(blendRgb(hexToRgb(scale.high), hexToRgb(scale.low), intensity), labelRoles, "label") : "label";
|
|
7939
8181
|
useIsomorphicLayoutEffect(() => {
|
|
7940
8182
|
if (!containerRef.current) return;
|
|
7941
8183
|
const next = resolveLabelRoles(createCssVariableResolver(containerRef.current));
|
|
@@ -7949,13 +8191,56 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
7949
8191
|
const extent = useMemo(() => getValueExtent(data), [data]);
|
|
7950
8192
|
const heatmapContext = useMemo(() => ({
|
|
7951
8193
|
extent,
|
|
7952
|
-
|
|
7953
|
-
}), [extent,
|
|
8194
|
+
fillVars
|
|
8195
|
+
}), [extent, fillVars]);
|
|
7954
8196
|
const columns = data.length;
|
|
7955
8197
|
const rows = Math.max(0, ...data.map((column) => column.data.length));
|
|
7956
8198
|
const groupLayout = useMemo(() => resolveColumnGroups(columnGroups, columns, 2), [columnGroups, columns]);
|
|
7957
8199
|
const { compactCellGap, compactCellSize, groupGap } = heatmapChartSettings;
|
|
7958
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]);
|
|
7959
8244
|
const buildTooltipData = useCallback((columnIndex, rowIndex) => {
|
|
7960
8245
|
const cell = data[columnIndex]?.data[rowIndex];
|
|
7961
8246
|
const group = groupLayout.columns[columnIndex]?.group;
|
|
@@ -8095,20 +8380,25 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8095
8380
|
});
|
|
8096
8381
|
const columnTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellWidth ?? 0}px, ${maxCellWidth ? `${maxCellWidth}px` : "1fr"})`;
|
|
8097
8382
|
const rowTrack = compact ? "var(--a8c-charts-dimension-heatmap-cell-size)" : `minmax(${minCellHeight ?? 0}px, ${maxCellHeight ? `${maxCellHeight}px` : "1fr"})`;
|
|
8098
|
-
const
|
|
8099
|
-
const
|
|
8100
|
-
const
|
|
8101
|
-
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;
|
|
8102
8390
|
const dataTrack = (column) => column.summary ? "minmax(auto, max-content)" : columnTrack;
|
|
8103
8391
|
const gapTrack = compact ? `minmax(${groupGap}px, 1fr)` : `${groupGap}px`;
|
|
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" : ""}`;
|
|
8104
8394
|
const gridStyle = {
|
|
8105
|
-
|
|
8106
|
-
gridTemplateColumns: `auto ${
|
|
8107
|
-
gridTemplateRows:
|
|
8395
|
+
...fillVars,
|
|
8396
|
+
gridTemplateColumns: `auto ${columnTracks}`,
|
|
8397
|
+
gridTemplateRows: Array(bands).fill(bandTracks).join(` ${groupGap}px `)
|
|
8108
8398
|
};
|
|
8109
8399
|
if (compact) {
|
|
8110
8400
|
gridStyle["--a8c-charts-dimension-heatmap-cell-gap"] = `${compactCellGap}px`;
|
|
8111
|
-
gridStyle["--a8c-charts-dimension-heatmap-cell-size"] = `${compactCellSize}px`;
|
|
8401
|
+
gridStyle["--a8c-charts-dimension-heatmap-cell-size"] = `${fit?.cellSize ?? compactCellSize}px`;
|
|
8112
8402
|
}
|
|
8113
8403
|
const summaryGaps = (columnIndex) => {
|
|
8114
8404
|
if (!data[columnIndex]?.summary) return {};
|
|
@@ -8128,6 +8418,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8128
8418
|
legendChildren: [],
|
|
8129
8419
|
trailingContent: nonLegendChildren,
|
|
8130
8420
|
gap,
|
|
8421
|
+
rootRef: chartRef,
|
|
8131
8422
|
className: clsx("heatmap-chart", heatmap_chart_module_default["heatmap-chart"], className, { [heatmap_chart_module_default["heatmap-chart--height-capped"]]: heightCapped }),
|
|
8132
8423
|
style: {
|
|
8133
8424
|
width: width || void 0,
|
|
@@ -8157,11 +8448,11 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8157
8448
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8158
8449
|
children: [/* @__PURE__ */ jsx("span", { style: {
|
|
8159
8450
|
gridColumn: 1,
|
|
8160
|
-
gridRow:
|
|
8451
|
+
gridRow: labelRowOf(0)
|
|
8161
8452
|
} }), data.map((column, columnIndex) => /* @__PURE__ */ jsx("span", {
|
|
8162
8453
|
style: {
|
|
8163
8454
|
gridColumn: columnLine(columnIndex),
|
|
8164
|
-
gridRow:
|
|
8455
|
+
gridRow: labelRowOf(bandOf(columnIndex))
|
|
8165
8456
|
},
|
|
8166
8457
|
className: clsx(heatmap_chart_module_default["heatmap-chart__col-label"], {
|
|
8167
8458
|
[heatmap_chart_module_default["heatmap-chart__col-label--summary"]]: column.summary,
|
|
@@ -8172,24 +8463,23 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8172
8463
|
}),
|
|
8173
8464
|
Array.from({ length: rows }).map((_row, rowIndex) => {
|
|
8174
8465
|
const labelVisible = !compact || rowIndex % 2 === 0;
|
|
8175
|
-
const gridRow = firstDataRow + rowIndex;
|
|
8176
8466
|
return /* @__PURE__ */ jsxs("div", {
|
|
8177
8467
|
role: "row",
|
|
8178
8468
|
"aria-rowindex": rowIndex + 1,
|
|
8179
8469
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8180
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
8470
|
+
children: [Array.from({ length: bands }).map((_band, band) => /* @__PURE__ */ jsx("span", {
|
|
8181
8471
|
"aria-hidden": "true",
|
|
8182
8472
|
className: heatmap_chart_module_default["heatmap-chart__row-label"],
|
|
8183
8473
|
style: {
|
|
8184
8474
|
gridColumn: 1,
|
|
8185
|
-
gridRow
|
|
8475
|
+
gridRow: dataRowOf(band, rowIndex)
|
|
8186
8476
|
},
|
|
8187
8477
|
children: labelVisible ? rowLabels[rowIndex] ?? "" : ""
|
|
8188
|
-
}), data.map((column, columnIndex) => {
|
|
8478
|
+
}, `row-label-${band}`)), data.map((column, columnIndex) => {
|
|
8189
8479
|
const cell = column.data[rowIndex];
|
|
8190
8480
|
const placement = {
|
|
8191
8481
|
gridColumn: columnLine(columnIndex),
|
|
8192
|
-
gridRow
|
|
8482
|
+
gridRow: dataRowOf(bandOf(columnIndex), rowIndex)
|
|
8193
8483
|
};
|
|
8194
8484
|
if (cell?.hidden) return /* @__PURE__ */ jsx("div", {
|
|
8195
8485
|
"aria-hidden": "true",
|
|
@@ -8203,7 +8493,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8203
8493
|
}, `cell-${columnIndex}-${rowIndex}`);
|
|
8204
8494
|
const value = cell?.value ?? null;
|
|
8205
8495
|
const present = isPresent(value);
|
|
8206
|
-
const filled = present && !column.summary;
|
|
8496
|
+
const filled = present && !column.summary && !isEmptyValue(value, extent);
|
|
8207
8497
|
const normalized = filled ? getNormalizedValue(value, extent) : 0;
|
|
8208
8498
|
const info = buildTooltipData(columnIndex, rowIndex);
|
|
8209
8499
|
const accessibleLabel = `${cellName(info)}: ${info.value === null ? __("No data", "jetpack-charts") : formatNumber(info.value)}`;
|
|
@@ -8239,11 +8529,11 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
|
|
|
8239
8529
|
role: "row",
|
|
8240
8530
|
"aria-hidden": "true",
|
|
8241
8531
|
className: heatmap_chart_module_default["heatmap-chart__row"],
|
|
8242
|
-
children:
|
|
8532
|
+
children: placed.groups.map((group, groupIndex) => /* @__PURE__ */ jsx("span", {
|
|
8243
8533
|
className: heatmap_chart_module_default["heatmap-chart__group-label"],
|
|
8244
8534
|
style: {
|
|
8245
8535
|
gridColumn: `${group.line} / span ${group.span}`,
|
|
8246
|
-
gridRow:
|
|
8536
|
+
gridRow: dataRowOf(group.band, rows)
|
|
8247
8537
|
},
|
|
8248
8538
|
children: group.label
|
|
8249
8539
|
}, `group-${groupIndex}`))
|
|
@@ -11113,6 +11403,7 @@ var leaderboard_chart_module_default = {
|
|
|
11113
11403
|
"interactiveRow": "a8ccharts-GovfoW-interactiveRow",
|
|
11114
11404
|
"is-overlay": "a8ccharts-GovfoW-is-overlay",
|
|
11115
11405
|
"label": "a8ccharts-GovfoW-label",
|
|
11406
|
+
"layeredRow": "a8ccharts-GovfoW-layeredRow",
|
|
11116
11407
|
"leaderboardChart": "a8ccharts-GovfoW-leaderboardChart",
|
|
11117
11408
|
"leaderboardChart__content": "a8ccharts-GovfoW-leaderboardChart__content",
|
|
11118
11409
|
"leaderboardChart__content--fit": "a8ccharts-GovfoW-leaderboardChart__content--fit",
|
|
@@ -11121,6 +11412,7 @@ var leaderboard_chart_module_default = {
|
|
|
11121
11412
|
"overlap": "a8ccharts-GovfoW-overlap",
|
|
11122
11413
|
"overlayLabel": "a8ccharts-GovfoW-overlayLabel",
|
|
11123
11414
|
"row": "a8ccharts-GovfoW-row",
|
|
11415
|
+
"rowButton": "a8ccharts-GovfoW-rowButton",
|
|
11124
11416
|
"stretch": "a8ccharts-GovfoW-stretch",
|
|
11125
11417
|
"valueContainer": "a8ccharts-GovfoW-valueContainer"
|
|
11126
11418
|
};
|
|
@@ -11171,6 +11463,16 @@ const defaultDeltaFormatter = (value) => {
|
|
|
11171
11463
|
const getBarWidth = (share) => `calc(${share}% - var(--a8c-charts-dimension-leaderboard-bar-hover-inset, 0px) * ${share} / 100)`;
|
|
11172
11464
|
const hasPreviousValue = (entry) => entry.previousValue != null && entry.previousShare != null;
|
|
11173
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
|
+
}
|
|
11174
11476
|
const BarLabel = ({ label }) => /* @__PURE__ */ jsx(Fragment$1, { children: typeof label === "string" ? /* @__PURE__ */ jsx(Text$1, {
|
|
11175
11477
|
className: leaderboard_chart_module_default.label,
|
|
11176
11478
|
children: label
|
|
@@ -11403,6 +11705,26 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
|
|
|
11403
11705
|
})
|
|
11404
11706
|
]
|
|
11405
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);
|
|
11406
11728
|
if (entry.onClick) return /* @__PURE__ */ jsxs("button", {
|
|
11407
11729
|
type: "button",
|
|
11408
11730
|
"data-row-index": rowIndex,
|
|
@@ -11436,6 +11758,210 @@ LeaderboardChartWithProvider.displayName = "LeaderboardChart";
|
|
|
11436
11758
|
const LeaderboardChart = attachSubComponents(LeaderboardChartWithProvider, { Legend });
|
|
11437
11759
|
const LeaderboardChartResponsive = attachSubComponents(withResponsive(LeaderboardChartWithProvider), { Legend });
|
|
11438
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
|
|
11439
11965
|
//#region src/charts/private/radial-wipe-animation/radial-wipe-animation.tsx
|
|
11440
11966
|
/**
|
|
11441
11967
|
* Renders a SVG mask that creates a radial wipe animation effect.
|
|
@@ -11488,18 +12014,13 @@ var pie_chart_module_default = {
|
|
|
11488
12014
|
//#region src/charts/pie-chart/pie-chart.tsx
|
|
11489
12015
|
/**
|
|
11490
12016
|
* Default tooltip renderer for pie charts.
|
|
11491
|
-
* Renders
|
|
12017
|
+
* Renders the default `label: value` tooltip content for the hovered segment.
|
|
11492
12018
|
*
|
|
11493
12019
|
* @param {PieChartRenderTooltipParams} params - The tooltip parameters containing the hovered data point
|
|
11494
12020
|
* @return {ReactNode} The rendered tooltip content
|
|
11495
12021
|
*/
|
|
11496
12022
|
const renderDefaultPieTooltip = ({ tooltipData }) => {
|
|
11497
|
-
return /* @__PURE__ */ jsx(
|
|
11498
|
-
data: tooltipData,
|
|
11499
|
-
top: 0,
|
|
11500
|
-
left: 0,
|
|
11501
|
-
renderContainer: false
|
|
11502
|
-
});
|
|
12023
|
+
return /* @__PURE__ */ jsx(LabelValueContent, { data: tooltipData });
|
|
11503
12024
|
};
|
|
11504
12025
|
/**
|
|
11505
12026
|
* Validates the pie chart data
|
|
@@ -11536,20 +12057,13 @@ const LABEL_TEXT_MODIFIER = {
|
|
|
11536
12057
|
* @param {PieChartProps} props - Component props
|
|
11537
12058
|
* @return {JSX.Element} The rendered chart component
|
|
11538
12059
|
*/
|
|
11539
|
-
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" }) => {
|
|
11540
12061
|
const legendInteractive = legend.interactive ?? false;
|
|
11541
12062
|
const legendPosition = legend.position ?? "bottom";
|
|
11542
12063
|
const providerTheme = useGlobalChartsTheme();
|
|
11543
12064
|
const chartId = useChartId(providedChartId);
|
|
11544
|
-
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = useTooltip();
|
|
11545
|
-
const standaloneScopeClass = useStandaloneScopeClass();
|
|
11546
|
-
const containerRef = useRef(null);
|
|
11547
12065
|
const rootRef = useRef(null);
|
|
11548
12066
|
const [labelRoles, setLabelRoles] = useState(null);
|
|
11549
|
-
const onMouseLeave = useCallback(() => {
|
|
11550
|
-
if (!withTooltips) return;
|
|
11551
|
-
hideTooltip();
|
|
11552
|
-
}, [withTooltips, hideTooltip]);
|
|
11553
12067
|
const { getElementStyles, isSeriesVisible, isColorPaletteResolved } = useGlobalChartsContext();
|
|
11554
12068
|
const { isValid, message } = validateData$1(data);
|
|
11555
12069
|
useLayoutEffect(() => {
|
|
@@ -11593,13 +12107,7 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
11593
12107
|
metadata: chartMetadata
|
|
11594
12108
|
});
|
|
11595
12109
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
11596
|
-
|
|
11597
|
-
className: clsx("pie-chart", pie_chart_module_default["pie-chart"], className),
|
|
11598
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
11599
|
-
className: pie_chart_module_default["error-message"],
|
|
11600
|
-
children: message
|
|
11601
|
-
})
|
|
11602
|
-
});
|
|
12110
|
+
const wipeMask = animation && !prefersReducedMotion ? `url(#radial-wipe-${chartId})` : null;
|
|
11603
12111
|
const padAngle = gapScale * (2 * Math.PI / data.length);
|
|
11604
12112
|
const dataWithIndex = visibleData.map((d) => {
|
|
11605
12113
|
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
@@ -11617,6 +12125,24 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
11617
12125
|
}).color;
|
|
11618
12126
|
}
|
|
11619
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
|
+
});
|
|
11620
12146
|
const legendElement = showLegend && /* @__PURE__ */ jsx(Legend, {
|
|
11621
12147
|
orientation: legend.orientation ?? "horizontal",
|
|
11622
12148
|
position: legendPosition,
|
|
@@ -11655,102 +12181,96 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
11655
12181
|
const innerRadius = thickness === 0 ? 0 : outerRadius * (1 - thickness);
|
|
11656
12182
|
const maxCornerRadius = (outerRadius - innerRadius) / 2;
|
|
11657
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
|
+
};
|
|
11658
12220
|
return /* @__PURE__ */ jsxs(Center, {
|
|
11659
|
-
ref:
|
|
12221
|
+
ref: chartRef,
|
|
11660
12222
|
className: pie_chart_module_default["pie-chart__plot"],
|
|
12223
|
+
...chartProps,
|
|
12224
|
+
"aria-label": ariaLabel ?? __("Pie chart", "jetpack-charts"),
|
|
11661
12225
|
children: [/* @__PURE__ */ jsxs("svg", {
|
|
12226
|
+
ref: svgRef,
|
|
11662
12227
|
viewBox: `0 0 ${width} ${height}`,
|
|
11663
12228
|
preserveAspectRatio: "xMidYMid meet",
|
|
11664
12229
|
width,
|
|
11665
12230
|
height,
|
|
11666
|
-
children: [
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
|
|
11674
|
-
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
groupProps.onMouseMove = handleMouseMove;
|
|
11710
|
-
groupProps.onMouseLeave = onMouseLeave;
|
|
11711
|
-
}
|
|
11712
|
-
const svgLabelSmall = providerTheme.svgLabelSmall;
|
|
11713
|
-
const fontSize = resolveFontSize(svgLabelSmall?.fontSize) ?? 12;
|
|
11714
|
-
const backgroundWidth = getStringWidth$1(arc.data.label, {
|
|
11715
|
-
fontSize,
|
|
11716
|
-
fontFamily: svgLabelSmall?.fontFamily,
|
|
11717
|
-
fontWeight: svgLabelSmall?.fontWeight
|
|
11718
|
-
}) + 12;
|
|
11719
|
-
const backgroundHeight = fontSize + 12;
|
|
11720
|
-
return /* @__PURE__ */ jsxs("g", {
|
|
11721
|
-
...groupProps,
|
|
11722
|
-
children: [/* @__PURE__ */ jsx("path", { ...pathProps }), showLabels && hasSpaceForLabel && /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
|
|
11723
|
-
className: pie_chart_module_default["pie-chart__label-plate"],
|
|
11724
|
-
x: centroidX - backgroundWidth / 2,
|
|
11725
|
-
y: centroidY - backgroundHeight / 2,
|
|
11726
|
-
width: backgroundWidth,
|
|
11727
|
-
height: backgroundHeight,
|
|
11728
|
-
rx: 4,
|
|
11729
|
-
ry: 4,
|
|
11730
|
-
pointerEvents: "none"
|
|
11731
|
-
}), /* @__PURE__ */ jsx("text", {
|
|
11732
|
-
className: clsx(pie_chart_module_default["pie-chart__label-text"], LABEL_TEXT_MODIFIER[pickLabelTextColor(fill, labelRoles, "label-inverse")]),
|
|
11733
|
-
x: centroidX,
|
|
11734
|
-
y: centroidY,
|
|
11735
|
-
dy: ".33em",
|
|
11736
|
-
fontSize,
|
|
11737
|
-
textAnchor: "middle",
|
|
11738
|
-
pointerEvents: "none",
|
|
11739
|
-
children: arc.data.label
|
|
11740
|
-
})] })]
|
|
11741
|
-
}, `arc-${index}`);
|
|
11742
|
-
});
|
|
11743
|
-
}
|
|
11744
|
-
}), !allSegmentsHidden && svgChildren]
|
|
11745
|
-
})]
|
|
11746
|
-
}), withTooltips && tooltipOpen && tooltipData && /* @__PURE__ */ jsx(BoundedTooltip, {
|
|
11747
|
-
top: tooltipTop || 0,
|
|
11748
|
-
left: tooltipLeft || 0,
|
|
11749
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
11750
|
-
className: standaloneScopeClass,
|
|
11751
|
-
role: "tooltip",
|
|
11752
|
-
children: renderTooltip({ tooltipData })
|
|
11753
|
-
})
|
|
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
|
|
11754
12274
|
})]
|
|
11755
12275
|
});
|
|
11756
12276
|
}
|
|
@@ -11785,18 +12305,13 @@ var pie_semi_circle_chart_module_default = {
|
|
|
11785
12305
|
//#region src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx
|
|
11786
12306
|
/**
|
|
11787
12307
|
* Default tooltip renderer for semi-circle pie charts.
|
|
11788
|
-
* Renders
|
|
12308
|
+
* Renders the default `label: value` tooltip content for the hovered segment.
|
|
11789
12309
|
*
|
|
11790
12310
|
* @param {PieSemiCircleChartRenderTooltipParams} params - The tooltip parameters containing the hovered data point
|
|
11791
12311
|
* @return {ReactNode} The rendered tooltip content
|
|
11792
12312
|
*/
|
|
11793
12313
|
const renderDefaultPieSemiCircleTooltip = ({ tooltipData }) => {
|
|
11794
|
-
return /* @__PURE__ */ jsx(
|
|
11795
|
-
data: tooltipData,
|
|
11796
|
-
top: 0,
|
|
11797
|
-
left: 0,
|
|
11798
|
-
renderContainer: false
|
|
11799
|
-
});
|
|
12314
|
+
return /* @__PURE__ */ jsx(LabelValueContent, { data: tooltipData });
|
|
11800
12315
|
};
|
|
11801
12316
|
const PAD_ANGLE = .03;
|
|
11802
12317
|
const DEFAULT_WIDTH$1 = 400;
|
|
@@ -11823,32 +12338,10 @@ const validateData = (data) => {
|
|
|
11823
12338
|
message: ""
|
|
11824
12339
|
};
|
|
11825
12340
|
};
|
|
11826
|
-
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" }) => {
|
|
11827
12342
|
const legendInteractive = legend.interactive ?? false;
|
|
11828
12343
|
const legendPosition = legend.position ?? "bottom";
|
|
11829
12344
|
const chartId = useChartId(providedChartId);
|
|
11830
|
-
const { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } = useTooltip();
|
|
11831
|
-
const standaloneScopeClass = useStandaloneScopeClass();
|
|
11832
|
-
const containerRef = useRef(null);
|
|
11833
|
-
const handleMouseMove = useCallback((event, arc) => {
|
|
11834
|
-
const bounds = containerRef.current?.getBoundingClientRect();
|
|
11835
|
-
if (!bounds) return;
|
|
11836
|
-
showTooltip({
|
|
11837
|
-
tooltipData: arc.data,
|
|
11838
|
-
tooltipLeft: event.clientX - bounds.left + tooltipOffsetX,
|
|
11839
|
-
tooltipTop: event.clientY - bounds.top + tooltipOffsetY
|
|
11840
|
-
});
|
|
11841
|
-
}, [
|
|
11842
|
-
showTooltip,
|
|
11843
|
-
tooltipOffsetX,
|
|
11844
|
-
tooltipOffsetY
|
|
11845
|
-
]);
|
|
11846
|
-
const handleMouseLeave = useCallback(() => {
|
|
11847
|
-
hideTooltip();
|
|
11848
|
-
}, [hideTooltip]);
|
|
11849
|
-
const handleArcMouseMove = useCallback((arc) => (event) => {
|
|
11850
|
-
handleMouseMove(event, arc);
|
|
11851
|
-
}, [handleMouseMove]);
|
|
11852
12345
|
const { isValid, message } = validateData(data);
|
|
11853
12346
|
const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
|
|
11854
12347
|
const dataWithPercentages = useDataWithPercentages(data);
|
|
@@ -11882,7 +12375,31 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
11882
12375
|
metadata: chartMetadata
|
|
11883
12376
|
});
|
|
11884
12377
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
12378
|
+
const wipeMask = animation && !prefersReducedMotion ? `url(#radial-wipe-${chartId})` : null;
|
|
11885
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
|
+
});
|
|
11886
12403
|
if (!isValid) {
|
|
11887
12404
|
const errorWidth = propHeight ? Math.min(propWidth || propHeight * 2, propHeight * 2) : effectiveWidth;
|
|
11888
12405
|
const errorHeight = errorWidth / 2;
|
|
@@ -11901,15 +12418,6 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
11901
12418
|
})
|
|
11902
12419
|
});
|
|
11903
12420
|
}
|
|
11904
|
-
const dataWithIndex = visibleData.map((d) => {
|
|
11905
|
-
const originalIndex = data.findIndex((item) => item.label === d.label);
|
|
11906
|
-
return {
|
|
11907
|
-
...d,
|
|
11908
|
-
index: originalIndex >= 0 ? originalIndex : 0
|
|
11909
|
-
};
|
|
11910
|
-
});
|
|
11911
|
-
const startAngle = clockwise ? -Math.PI / 2 : Math.PI / 2;
|
|
11912
|
-
const endAngle = clockwise ? Math.PI / 2 : -Math.PI / 2;
|
|
11913
12421
|
const legendElement = showLegend && /* @__PURE__ */ jsx(Legend, {
|
|
11914
12422
|
orientation: legend.orientation ?? "horizontal",
|
|
11915
12423
|
position: legendPosition,
|
|
@@ -11942,52 +12450,60 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
11942
12450
|
const height = width / 2;
|
|
11943
12451
|
const radius = height;
|
|
11944
12452
|
const innerRadius = radius * (1 - thickness);
|
|
12453
|
+
const path = arc({
|
|
12454
|
+
innerRadius,
|
|
12455
|
+
outerRadius: radius,
|
|
12456
|
+
cornerRadius: 3
|
|
12457
|
+
});
|
|
11945
12458
|
return /* @__PURE__ */ jsxs(Center, {
|
|
11946
|
-
ref:
|
|
12459
|
+
ref: chartRef,
|
|
11947
12460
|
className: pie_semi_circle_chart_module_default["pie-semi-circle-chart__plot"],
|
|
12461
|
+
...chartProps,
|
|
12462
|
+
"aria-label": ariaLabel ?? __("Semi-circle chart", "jetpack-charts"),
|
|
11948
12463
|
children: [/* @__PURE__ */ jsxs("svg", {
|
|
12464
|
+
ref: svgRef,
|
|
11949
12465
|
width,
|
|
11950
12466
|
height,
|
|
11951
12467
|
viewBox: `0 0 ${width} ${height}`,
|
|
11952
|
-
children: [
|
|
11953
|
-
|
|
11954
|
-
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
11988
|
-
|
|
11989
|
-
|
|
11990
|
-
/* @__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, {
|
|
11991
12507
|
textAnchor: "middle",
|
|
11992
12508
|
verticalAnchor: "start",
|
|
11993
12509
|
y: -40,
|
|
@@ -11999,18 +12515,13 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
11999
12515
|
y: -20,
|
|
12000
12516
|
className: pie_semi_circle_chart_module_default.note,
|
|
12001
12517
|
children: note
|
|
12002
|
-
})] }),
|
|
12003
|
-
|
|
12004
|
-
|
|
12005
|
-
|
|
12006
|
-
|
|
12007
|
-
|
|
12008
|
-
|
|
12009
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
12010
|
-
className: standaloneScopeClass,
|
|
12011
|
-
role: "tooltip",
|
|
12012
|
-
children: renderTooltip({ tooltipData })
|
|
12013
|
-
})
|
|
12518
|
+
})] }), svgChildren]
|
|
12519
|
+
})
|
|
12520
|
+
]
|
|
12521
|
+
}), /* @__PURE__ */ jsx(PieSelectionOutput, {
|
|
12522
|
+
...selectionOutputProps,
|
|
12523
|
+
keyboardTooltipAnchor: selectedArc && getKeyboardTooltipAnchor(width / 2, height, path.centroid(selectedArc)),
|
|
12524
|
+
renderTooltip
|
|
12014
12525
|
})]
|
|
12015
12526
|
});
|
|
12016
12527
|
}
|
|
@@ -12236,6 +12747,6 @@ function TrendIndicator({ direction, value, className, style, showIcon = true })
|
|
|
12236
12747
|
});
|
|
12237
12748
|
}
|
|
12238
12749
|
//#endregion
|
|
12239
|
-
export { AccessibleTooltip, AreaChartResponsive as AreaChart, AreaChart as AreaChartUnresponsive, BarChartResponsive as BarChart, BarChart as BarChartUnresponsive, BarListChartResponsive as BarListChart, BarListChart as BarListChartUnresponsive, BaseTooltip, ConversionFunnelChartWithProvider as ConversionFunnelChart, GeoChartResponsive as GeoChart, GeoChartWithProvider as GeoChartUnresponsive, GlobalChartsContext, GlobalChartsProvider, GlobalChartsProvider as ThemeProvider, GoogleDataTableColumnRoleType, HeatmapChartResponsive as HeatmapChart, HeatmapChart as HeatmapChartUnresponsive, LeaderboardChartResponsive as LeaderboardChart, LeaderboardChart as LeaderboardChartUnresponsive, Legend, LineChartResponsive as LineChart, LineChart as LineChartUnresponsive, PieChartResponsive as PieChart, PieChart as PieChartUnresponsive, PieSemiCircleChartResponsive as PieSemiCircleChart, PieSemiCircleChart as PieSemiCircleChartUnresponsive, Sparkline, SparklineUnresponsive, TrendIndicator, buildCalendarHeatmapData, buildMonthCalendarHeatmapData, defaultTheme, formatMetricValue, formatPercentage, getBucketInfo, getColorDistance, hexToRgba, isValidHexColor, lightenHexColor, mergeThemes, mixHexColors, normalizeColorToHex, parseAsLocalDate, parseHslString, prefersLightText, relativeLuminance, resolveCssVariable, useCalendarHeatmapData, useChartFormatting, useChartLegendItems, useChartRegistration, useChartScopeElement, useGlobalChartsContext, useGlobalChartsTheme, useLeaderboardLegendItems, useMonthCalendarHeatmapData, validateHexColor };
|
|
12750
|
+
export { AccessibleTooltip, AreaChartResponsive as AreaChart, AreaChart as AreaChartUnresponsive, BarChartResponsive as BarChart, BarChart as BarChartUnresponsive, BarListChartResponsive as BarListChart, BarListChart as BarListChartUnresponsive, BaseTooltip, ConversionFunnelChartWithProvider as ConversionFunnelChart, GeoChartResponsive as GeoChart, GeoChartWithProvider as GeoChartUnresponsive, GlobalChartsContext, GlobalChartsProvider, GlobalChartsProvider as ThemeProvider, GoogleDataTableColumnRoleType, HeatmapChartResponsive as HeatmapChart, HeatmapChart as HeatmapChartUnresponsive, LeaderboardChartResponsive as LeaderboardChart, LeaderboardChart as LeaderboardChartUnresponsive, Legend, LineChartResponsive as LineChart, LineChart as LineChartUnresponsive, PieChartResponsive as PieChart, PieChart as PieChartUnresponsive, PieSemiCircleChartResponsive as PieSemiCircleChart, PieSemiCircleChart as PieSemiCircleChartUnresponsive, Sparkline, SparklineUnresponsive, TooltipBox, TrendIndicator, XYChartTooltip, buildCalendarHeatmapData, buildMonthCalendarHeatmapData, defaultTheme, formatMetricValue, formatPercentage, getBucketInfo, getColorDistance, hexToRgba, isValidHexColor, lightenHexColor, mergeThemes, mixHexColors, normalizeColorToHex, parseAsLocalDate, parseHslString, prefersLightText, relativeLuminance, resolveCssVariable, useCalendarHeatmapData, useChartFormatting, useChartLegendItems, useChartRegistration, useChartScopeElement, useGlobalChartsContext, useGlobalChartsTheme, useLeaderboardLegendItems, useMonthCalendarHeatmapData, validateHexColor };
|
|
12240
12751
|
|
|
12241
12752
|
//# sourceMappingURL=index.js.map
|