@automattic/charts 3.1.1 → 3.2.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/TOKENS.md +51 -12
  3. package/dist/index.cjs +292 -200
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +7 -1
  6. package/dist/index.d.cts +223 -127
  7. package/dist/index.d.ts +223 -127
  8. package/dist/index.js +291 -199
  9. package/dist/index.js.map +1 -1
  10. package/package.json +8 -8
  11. package/src/charts/bar-chart/bar-chart.tsx +36 -10
  12. package/src/charts/bar-chart/test/bar-chart-pointer-events.test.tsx +67 -0
  13. package/src/charts/bar-chart/test/bar-chart.test.tsx +79 -0
  14. package/src/charts/bar-list-chart/bar-list-chart.tsx +40 -2
  15. package/src/charts/bar-list-chart/test/bar-list-chart.test.tsx +38 -0
  16. package/src/charts/line-chart/line-chart.tsx +16 -1
  17. package/src/charts/line-chart/test/line-chart.test.tsx +47 -0
  18. package/src/charts/sparkline/sparkline.tsx +9 -3
  19. package/src/charts/sparkline/types.ts +1 -1
  20. package/src/components/tooltip/accessible-tooltip.tsx +32 -2
  21. package/src/components/tooltip/test/accessible-tooltip.test.tsx +68 -0
  22. package/src/hooks/test/use-xychart-theme-provider-override.test.tsx +4 -4
  23. package/src/hooks/test/use-xychart-theme-style-reads.test.tsx +17 -10
  24. package/src/hooks/test/use-xychart-theme.test.tsx +50 -5
  25. package/src/hooks/use-xychart-theme.ts +14 -20
  26. package/src/providers/chart-context/global-charts-provider.tsx +44 -33
  27. package/src/providers/chart-context/private/series-palette.ts +45 -0
  28. package/src/providers/chart-context/private/theme-override-vars.ts +46 -2
  29. package/src/providers/chart-context/private/with-catalog-pointers.ts +45 -2
  30. package/src/providers/chart-context/test/sparse-theme.test.ts +16 -2
  31. package/src/providers/chart-context/test/theme-override-vars.test.ts +65 -0
  32. package/src/providers/chart-context/test/use-global-charts-theme.test.tsx +8 -1
  33. package/src/providers/chart-context/test/with-catalog-pointers.test.ts +57 -0
  34. package/src/providers/chart-context/themes.ts +8 -3
  35. package/src/styles/chart-scope.scss +52 -24
  36. package/src/styles/test/chart-scope.test.ts +22 -9
  37. package/src/types.ts +148 -31
  38. package/src/utils/get-styles.ts +7 -1
package/dist/index.cjs CHANGED
@@ -17,7 +17,7 @@ var __copyProps = (to, from, except, desc) => {
17
17
  }
18
18
  return to;
19
19
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
21
21
  value: mod,
22
22
  enumerable: true
23
23
  }) : target, mod));
@@ -28,7 +28,7 @@ let _wordpress_i18n = require("@wordpress/i18n");
28
28
  let clsx = require("clsx");
29
29
  clsx = __toESM(clsx, 1);
30
30
  let react = require("react");
31
- react = __toESM(react, 1);
31
+ react = __toESM(react);
32
32
  let _visx_vendor_d3_color = require("@visx/vendor/d3-color");
33
33
  let date_fns = require("date-fns");
34
34
  let _visx_text = require("@visx/text");
@@ -252,7 +252,8 @@ const formatPercentage = (value) => {
252
252
  */
253
253
  const getLongestTickWidth = (ticks, formatTick, labelStyle) => {
254
254
  const formattedTicks = ticks.map((tick) => formatTick(tick, 0, []));
255
- return (0, _visx_text.getStringWidth)(formattedTicks.reduce((longest, current) => longest.length >= current.length ? longest : current, formattedTicks[0]), labelStyle);
255
+ const longestTick = formattedTicks.reduce((longest, current) => longest.length >= current.length ? longest : current, formattedTicks[0]);
256
+ return (0, _visx_text.getStringWidth)(longestTick, labelStyle);
256
257
  };
257
258
  //#endregion
258
259
  //#region src/utils/get-styles.ts
@@ -762,6 +763,16 @@ const getChartColor = (index, colorCache) => {
762
763
  const fallbackLightness = BASE_LIGHTNESS + index % LIGHTNESS_VARIATION_STEPS * LIGHTNESS_INCREMENT;
763
764
  return (0, _visx_vendor_d3_color.hsl)(Math.round(fallbackHue), fallbackSaturation / 100, fallbackLightness / 100).formatHex();
764
765
  };
766
+ /**
767
+ * The catalog role holding one series-palette slot.
768
+ *
769
+ * @param slot - The one-based slot number.
770
+ * @return The role name.
771
+ */
772
+ const seriesRole = (slot) => `--a8c-charts-color-series-${slot}`;
773
+ const SERIES_SLOT_1_FALLBACK = "#3858e9";
774
+ /** The catalog pointer for every slot, in slot order. */
775
+ const SERIES_PALETTE_POINTERS = Array.from({ length: 5 }, (_, index) => index === 0 ? `var(${seriesRole(1)}, ${SERIES_SLOT_1_FALLBACK})` : `var(${seriesRole(index + 1)})`);
765
776
  //#endregion
766
777
  //#region src/providers/chart-context/private/theme-override-vars.ts
767
778
  const ROLE_FOR_FIELD = [
@@ -769,8 +780,22 @@ const ROLE_FOR_FIELD = [
769
780
  ["--a8c-charts-color-grid", (theme) => theme.gridStyles?.stroke],
770
781
  ["--a8c-charts-color-axis", (theme) => theme.xAxisLineStyles?.stroke],
771
782
  ["--a8c-charts-color-tick", (theme) => theme.xTickLineStyles?.stroke],
772
- ["--a8c-charts-color-label-axis", (theme) => theme.svgLabelSmall?.fill]
783
+ ["--a8c-charts-color-label-axis", (theme) => theme.svgLabelSmall?.fill],
784
+ ["--a8c-charts-color-label-background", (theme) => theme.labelBackgroundColor],
785
+ ["--a8c-charts-color-label-on-fill", (theme) => theme.labelTextColor],
786
+ ...Array.from({ length: 5 }, (_, index) => [seriesRole(index + 1), (theme) => theme.colors?.[index]])
773
787
  ];
788
+ let warnedAboutExtraColors = false;
789
+ /**
790
+ * Warns once when a consumer passes more colors than there are slots to publish them into.
791
+ *
792
+ * @param count - How many entries `theme.colors` holds.
793
+ */
794
+ function warnOnceAboutExtraColors(count) {
795
+ if (warnedAboutExtraColors || process.env.NODE_ENV === "production") return;
796
+ warnedAboutExtraColors = true;
797
+ console.warn(`[Charts] theme.colors holds ${count} colors and the palette has 5 slots, so entries past the 5th are ignored. Set a per-series color with \`options.stroke\` instead.`);
798
+ }
774
799
  /**
775
800
  * The variable a `theme` prop override is published as, one layer outside the role itself.
776
801
  *
@@ -784,7 +809,7 @@ ROLE_FOR_FIELD.map(([role]) => role);
784
809
  /**
785
810
  * Whether a value reads the role it is being published for, which would make the catalog entry depend on itself.
786
811
  *
787
- * The dependency runs `<role>: var(<role>-theme, …)`, so a value naming `<role>` closes a cycle through the catalog entry. CSS marks every custom property in a cycle invalid at computed-value time — the role's own fallback is *not* used, so the token resolves to nothing and every chart loses that colour. Verified in Chrome: `--role-theme: var(--role, blue); --role: var(--role-theme, green)` leaves `--role` empty, not `green`.
812
+ * The dependency runs `<role>: var(<role>-theme, …)`, so a value naming `<role>` closes a cycle through the catalog entry. CSS marks every custom property in a cycle invalid at computed-value time — the role's own fallback is *not* used, so the token resolves to nothing and every chart loses that color. Verified in Chrome: `--role-theme: var(--role, blue); --role: var(--role-theme, green)` leaves `--role` empty, not `green`.
788
813
  *
789
814
  * Three things this has to get right, none of which a plain substring test gets:
790
815
  *
@@ -800,10 +825,12 @@ ROLE_FOR_FIELD.map(([role]) => role);
800
825
  */
801
826
  const readsOwnRole = (value, role) => value.trim() === role || new RegExp(`var\\(\\s*${role.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(value);
802
827
  /**
803
- * Maps a sparse consumer theme onto the theme-layer variables its overridden catalog roles read, so CSS-painted and JS-resolved colours read one source.
828
+ * Maps a sparse consumer theme onto the theme-layer variables its overridden catalog roles read, so CSS-painted and JS-resolved colors read one source.
804
829
  *
805
830
  * A value that reads the role it would override is left unpublished — that is the default theme's own pointer surviving `mergeThemes`, and publishing it would invalidate the role. The role is still reported in `roles`: `withCatalogPointers` restores its theme field to the catalog pointer either way, so CSS and visx agree on the catalog default rather than visx painting a literal CSS never sees.
806
831
  *
832
+ * `theme.colors` publishes through the same mechanism, one slot per entry, so a CSS declaration of `--a8c-charts-color-series-N` still beats it and a short array leaves the later slots unset rather than blank.
833
+ *
807
834
  * @param theme - The consumer's `theme` prop, before merging with the default theme.
808
835
  * @return The wrapper's custom properties, and the roles the consumer overrode.
809
836
  */
@@ -812,6 +839,7 @@ const themeOverrideVars = (theme) => {
812
839
  vars: {},
813
840
  roles: []
814
841
  };
842
+ if (Array.isArray(theme.colors) && theme.colors.length > 5) warnOnceAboutExtraColors(theme.colors.length);
815
843
  const vars = {};
816
844
  const roles = [];
817
845
  for (const [role, read] of ROLE_FOR_FIELD) {
@@ -832,15 +860,9 @@ const themeOverrideVars = (theme) => {
832
860
  */
833
861
  const defaultTheme = {
834
862
  backgroundColor: "var(--a8c-charts-color-background, #fff)",
835
- labelBackgroundColor: "transparent",
863
+ labelBackgroundColor: "var(--a8c-charts-color-label-background, transparent)",
836
864
  labelTextColor: "var(--a8c-charts-color-label-on-fill, #FFFFFF)",
837
- colors: [
838
- "#98C8DF",
839
- "#006DAB",
840
- "#A6DC80",
841
- "#1F9828",
842
- "#FF8C8F"
843
- ],
865
+ colors: [...SERIES_PALETTE_POINTERS],
844
866
  gridStyles: {
845
867
  stroke: "var(--a8c-charts-color-grid, #dbdbdb)",
846
868
  strokeWidth: 1
@@ -920,7 +942,23 @@ const defaultTheme = {
920
942
  };
921
943
  //#endregion
922
944
  //#region src/providers/chart-context/private/with-catalog-pointers.ts
945
+ /**
946
+ * The pointer one palette slot is restored to.
947
+ *
948
+ * Unlike the other roles, this keeps the consumer's own color as the pointer's terminal literal instead of the catalog's. The literal is only ever reached where `getComputedStyle` resolves nothing — SSR and jsdom — and there the palette is the one field where falling back to the catalog default would be visible: every series would paint the same seeded blue. In a browser the slot resolves first, so a CSS declaration of it still outranks the consumer's `theme.colors`.
949
+ *
950
+ * @param index - The slot's zero-based index in `colors`.
951
+ * @param value - The merged theme's entry for it.
952
+ * @return The catalog pointer for that slot.
953
+ */
954
+ const seriesPointer = (index, value) => {
955
+ const role = seriesRole(index + 1);
956
+ if (typeof value === "string" && value.startsWith(`var(${role}`)) return value;
957
+ if (typeof value !== "string" || value === "") return SERIES_PALETTE_POINTERS[index];
958
+ return `var(${role}, ${value})`;
959
+ };
923
960
  const CATALOG_RESTORE_FOR_ROLE = {
961
+ ...Object.fromEntries(Array.from({ length: 5 }, (_, index) => [seriesRole(index + 1), (theme) => ({ colors: SERIES_PALETTE_POINTERS.map((_pointer, slot) => seriesPointer(slot, theme.colors?.[slot])) })])),
924
962
  "--a8c-charts-color-background": () => ({ backgroundColor: defaultTheme.backgroundColor }),
925
963
  "--a8c-charts-color-grid": (theme) => ({ gridStyles: {
926
964
  ...theme.gridStyles,
@@ -937,14 +975,16 @@ const CATALOG_RESTORE_FOR_ROLE = {
937
975
  "--a8c-charts-color-label-axis": (theme) => ({ svgLabelSmall: {
938
976
  ...theme.svgLabelSmall,
939
977
  fill: defaultTheme.svgLabelSmall.fill
940
- } })
978
+ } }),
979
+ "--a8c-charts-color-label-background": () => ({ labelBackgroundColor: defaultTheme.labelBackgroundColor }),
980
+ "--a8c-charts-color-label-on-fill": () => ({ labelTextColor: defaultTheme.labelTextColor })
941
981
  };
942
982
  /**
943
983
  * Restores the mapped theme fields of `overriddenRoles` to their catalog pointer, so the theme-layer variable `themeOverrideVars` writes on the provider wrapper is the only carrier for an overridden role — CSS and the JS bridge (`useXYChartTheme`) then resolve it through the same cascade instead of visx reading a baked literal that can disagree with a closer CSS override.
944
984
  *
945
985
  * This covers roles `themeOverrideVars` deliberately left unpublished as well as the ones it published. A value that reads its own role is not publishable, but leaving visx the consumer's literal is what the whole mechanism exists to prevent: `theme={ { gridStyles: { stroke: 'var(--brand, var(--a8c-charts-color-grid, red))' } } }` would have CSS paint the catalog default while visx painted `--brand`.
946
986
  *
947
- * Every field outside the five mapped roles is left exactly as `merged` provided it: those aren't published as theme-layer vars, so rewriting them would erase a consumer's override with no replacement carrier.
987
+ * Every field outside the mapped roles is left exactly as `merged` provided it: those aren't published as theme-layer vars, so rewriting them would erase a consumer's override with no replacement carrier.
948
988
  *
949
989
  * @param merged - The consumer theme merged onto `defaultTheme` (`mergeThemes` output).
950
990
  * @param overriddenRoles - The catalog roles the consumer overrode, from `themeOverrideVars`.
@@ -989,29 +1029,26 @@ const GlobalChartsProvider = ({ children, theme }) => {
989
1029
  const [isColorPaletteResolved, setIsColorPaletteResolved] = (0, react.useState)(false);
990
1030
  (0, react.useLayoutEffect)(() => {
991
1031
  setIsColorPaletteResolved(false);
992
- const { colors } = providerTheme;
993
1032
  const resolvedColors = [];
994
1033
  const hues = [];
995
1034
  const existingHslColors = [];
996
1035
  let minHue = 360;
997
1036
  let maxHue = 0;
998
- if (Array.isArray(colors)) {
999
- for (const color of colors) if (color && typeof color === "string") {
1000
- const normalizedColor = normalizeColorToHex(color, wrapperRef.current, resolveCssVariable);
1001
- if (normalizedColor.startsWith("#")) {
1002
- resolvedColors.push(normalizedColor);
1003
- const hslColor = (0, _visx_vendor_d3_color.hsl)(normalizedColor);
1004
- if (!isNaN(hslColor.h)) {
1005
- const hslTuple = [
1006
- hslColor.h,
1007
- hslColor.s * 100,
1008
- hslColor.l * 100
1009
- ];
1010
- hues.push(hslTuple[0]);
1011
- existingHslColors.push(hslTuple);
1012
- minHue = Math.min(minHue, hslTuple[0]);
1013
- maxHue = Math.max(maxHue, hslTuple[0]);
1014
- }
1037
+ for (const color of providerTheme.colors ?? SERIES_PALETTE_POINTERS) {
1038
+ const normalizedColor = normalizeColorToHex(color, wrapperRef.current, resolveCssVariable);
1039
+ if (normalizedColor.startsWith("#")) {
1040
+ resolvedColors.push(normalizedColor);
1041
+ const hslColor = (0, _visx_vendor_d3_color.hsl)(normalizedColor);
1042
+ if (!isNaN(hslColor.h)) {
1043
+ const hslTuple = [
1044
+ hslColor.h,
1045
+ hslColor.s * 100,
1046
+ hslColor.l * 100
1047
+ ];
1048
+ hues.push(hslTuple[0]);
1049
+ existingHslColors.push(hslTuple);
1050
+ minHue = Math.min(minHue, hslTuple[0]);
1051
+ maxHue = Math.max(maxHue, hslTuple[0]);
1015
1052
  }
1016
1053
  }
1017
1054
  }
@@ -1027,9 +1064,10 @@ const GlobalChartsProvider = ({ children, theme }) => {
1027
1064
  if (colorCache.colors.length > 0) setIsColorPaletteResolved(true);
1028
1065
  }, [colorCache]);
1029
1066
  const [groupToColorMap, setGroupToColorMap] = (0, react.useState)(() => /* @__PURE__ */ new Map());
1067
+ const paletteKey = colorCache.colors.join(",");
1030
1068
  (0, react.useEffect)(() => {
1031
1069
  setGroupToColorMap(/* @__PURE__ */ new Map());
1032
- }, [providerTheme.colors]);
1070
+ }, [paletteKey]);
1033
1071
  const registerChart = (0, react.useCallback)((id, data) => {
1034
1072
  setCharts((prev) => new Map(prev).set(id, data));
1035
1073
  }, []);
@@ -1242,27 +1280,13 @@ const useXYChartTheme = (data) => {
1242
1280
  return (0, react.useMemo)(() => {
1243
1281
  const resolve = createCssVariableResolver(scopeElement);
1244
1282
  const resolveColor = (value) => value ? resolve(value) ?? value : value;
1245
- const seriesColors = JSON.parse(seriesColorKey);
1283
+ const paletteColors = [...JSON.parse(seriesColorKey), ...theme.colors ?? []].map((color) => resolveColor(color)).filter((color) => Boolean(color) && !color.includes("var("));
1284
+ const htmlLabelColor = resolveColor(theme.svgLabelSmall?.fill);
1246
1285
  return (0, _visx_xychart.buildChartTheme)({
1247
1286
  ...theme,
1248
- colors: [...seriesColors, ...theme.colors ?? []],
1287
+ colors: paletteColors,
1249
1288
  backgroundColor: resolveColor(theme.backgroundColor),
1250
- gridStyles: theme.gridStyles && {
1251
- ...theme.gridStyles,
1252
- stroke: resolveColor(theme.gridStyles.stroke)
1253
- },
1254
- xAxisLineStyles: theme.xAxisLineStyles && {
1255
- ...theme.xAxisLineStyles,
1256
- stroke: resolveColor(theme.xAxisLineStyles.stroke)
1257
- },
1258
- xTickLineStyles: theme.xTickLineStyles && {
1259
- ...theme.xTickLineStyles,
1260
- stroke: resolveColor(theme.xTickLineStyles.stroke)
1261
- },
1262
- svgLabelSmall: theme.svgLabelSmall && {
1263
- ...theme.svgLabelSmall,
1264
- fill: resolveColor(theme.svgLabelSmall.fill)
1265
- }
1289
+ htmlLabel: htmlLabelColor ? { color: htmlLabelColor } : void 0
1266
1290
  });
1267
1291
  }, [
1268
1292
  theme,
@@ -1359,11 +1383,12 @@ const useChartMargin = (height, options, data, theme, horizontal = false) => {
1359
1383
  if (options.axis?.y?.tickValues?.length) return options.axis.y.tickValues;
1360
1384
  const minY = Math.min(...allDataPoints.map((d) => d.value));
1361
1385
  const maxY = Math.max(...allDataPoints.map((d) => d.value));
1362
- return (0, _visx_scale.getTicks)((0, _visx_scale.createScale)({
1386
+ const yScale = (0, _visx_scale.createScale)({
1363
1387
  ...options.yScale,
1364
1388
  domain: [minY, maxY],
1365
1389
  range: [height, 0]
1366
- }), options.axis?.y?.numTicks);
1390
+ });
1391
+ return (0, _visx_scale.getTicks)(yScale, options.axis?.y?.numTicks);
1367
1392
  }, [
1368
1393
  options,
1369
1394
  data,
@@ -1488,7 +1513,7 @@ const MIN_PIXEL_SIZE = 3;
1488
1513
  /**
1489
1514
  * Pixel size for zero-value bars (1px less than near-zero to be visually distinguishable).
1490
1515
  */
1491
- const ZERO_PIXEL_SIZE = MIN_PIXEL_SIZE - 1;
1516
+ const ZERO_PIXEL_SIZE = 2;
1492
1517
  const useZeroValueDisplay = (data, options = { enabled: false }) => {
1493
1518
  const { enabled, valueAxisLength } = options;
1494
1519
  return (0, react.useMemo)(() => {
@@ -2104,8 +2129,14 @@ const BaseTooltip = ({ data, top, left, component: Component = DefaultTooltipCon
2104
2129
  };
2105
2130
  //#endregion
2106
2131
  //#region src/components/tooltip/accessible-tooltip.tsx
2107
- const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocusedClassName, series = [], mode = "group", ...props }) => {
2132
+ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocusedClassName, series = [], mode = "group", verticalCrosshairStyle, horizontalCrosshairStyle, ...props }) => {
2108
2133
  const tooltipContext = (0, react.useContext)(_visx_xychart.TooltipContext);
2134
+ const scopeElement = useChartScopeElement();
2135
+ const gridStroke = useGlobalChartsTheme().gridStyles?.stroke;
2136
+ const crosshairStroke = (0, react.useMemo)(() => {
2137
+ const stroke = gridStroke ? resolveCssVariable(gridStroke, scopeElement) : null;
2138
+ return stroke ? { stroke } : void 0;
2139
+ }, [gridStroke, scopeElement]);
2109
2140
  const tooltipData = (0, react.useMemo)(() => {
2110
2141
  if (mode !== "individual") return [];
2111
2142
  if (series.length === 0) return [];
@@ -2184,10 +2215,18 @@ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardF
2184
2215
  ]);
2185
2216
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.Tooltip, {
2186
2217
  ...props,
2218
+ verticalCrosshairStyle: {
2219
+ ...crosshairStroke,
2220
+ ...verticalCrosshairStyle
2221
+ },
2222
+ horizontalCrosshairStyle: {
2223
+ ...crosshairStroke,
2224
+ ...horizontalCrosshairStyle
2225
+ },
2187
2226
  renderTooltip: focusableRenderTooltip
2188
2227
  });
2189
2228
  };
2190
- const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating, setIsNavigating, chartRef, totalPoints }) => {
2229
+ const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating, setIsNavigating, chartRef, totalPoints, onActivate }) => {
2191
2230
  return {
2192
2231
  tooltipRef: (0, react.useCallback)((element) => {
2193
2232
  if (element && selectedIndex !== void 0) element.focus();
@@ -2228,13 +2267,14 @@ const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating,
2228
2267
  setSelectedIndex(void 0);
2229
2268
  setIsNavigating(false);
2230
2269
  chartRef.current?.focus();
2231
- }
2270
+ } else if ((event.key === "Enter" || event.key === " ") && selectedIndex !== void 0) onActivate?.(selectedIndex);
2232
2271
  }, [
2233
2272
  totalPoints,
2234
2273
  selectedIndex,
2235
2274
  setSelectedIndex,
2236
2275
  setIsNavigating,
2237
- chartRef
2276
+ chartRef,
2277
+ onActivate
2238
2278
  ])
2239
2279
  };
2240
2280
  };
@@ -3001,7 +3041,7 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
3001
3041
  style: {
3002
3042
  width: `44px`,
3003
3043
  height: `44px`,
3004
- transform: `translate(${44 / 2}px, 0)`
3044
+ transform: `translate(22px, 0)`
3005
3045
  },
3006
3046
  "aria-label": title || (0, _wordpress_i18n.__)("View details", "jetpack-charts"),
3007
3047
  children: renderLabel({
@@ -3422,7 +3462,7 @@ const LineChartScalesRef = ({ chartRef, width, height, margin }) => {
3422
3462
  ]);
3423
3463
  return null;
3424
3464
  };
3425
- const LineChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, renderGlyph = defaultRenderGlyph, glyphStyle = {}, withLegendGlyph = false, withGradientFill = false, smoothing = true, curveType, renderTooltip = renderDefaultTooltip, withStartGlyphs = false, withEndGlyphs = false, animation, options = {}, onPointerDown = void 0, onPointerUp = void 0, onPointerMove = void 0, onPointerOut = void 0, zoomable = false, rescaleYOnVisibilityChange = true, defaultHiddenSeries, children, gridVisibility, gap = "md" }, ref) => {
3465
+ const LineChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, renderGlyph = defaultRenderGlyph, glyphStyle = {}, withLegendGlyph = false, withGradientFill = false, smoothing = true, curveType, renderTooltip = renderDefaultTooltip, 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) => {
3426
3466
  const legendInteractive = legend.interactive ?? false;
3427
3467
  const legendCollapseGroups = legend.collapseGroups ?? false;
3428
3468
  const legendShape = legend.shape ?? "line";
@@ -3484,13 +3524,23 @@ const LineChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartI
3484
3524
  }
3485
3525
  return min < max ? [min, max] : void 0;
3486
3526
  }, [rescaleYOnVisibilityChange, dataSorted]);
3527
+ const activateSelectedPoint = (0, react.useCallback)((index) => {
3528
+ const series = dataSorted[0];
3529
+ const datum = series?.data[index];
3530
+ if (series && datum) onDatumActivate?.({
3531
+ datum,
3532
+ index,
3533
+ key: series.label
3534
+ });
3535
+ }, [dataSorted, onDatumActivate]);
3487
3536
  const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
3488
3537
  selectedIndex,
3489
3538
  setSelectedIndex,
3490
3539
  isNavigating,
3491
3540
  setIsNavigating,
3492
3541
  chartRef,
3493
- totalPoints: dataSorted[0]?.data.length || 0
3542
+ totalPoints: dataSorted[0]?.data.length || 0,
3543
+ onActivate: activateSelectedPoint
3494
3544
  });
3495
3545
  const chartOptions = (0, react.useMemo)(() => {
3496
3546
  const { tickResolution, tickFormat, ...xAxisOptions } = options?.axis?.x ?? {};
@@ -3554,36 +3604,38 @@ const LineChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartI
3554
3604
  const defaultMargin = useChartMargin(height, chartOptions, dataSorted, theme);
3555
3605
  const error = validateData$4(dataSorted);
3556
3606
  const isDataValid = !error;
3607
+ const legendItems = useChartLegendItems(dataSorted, (0, react.useMemo)(() => ({
3608
+ withGlyph: withLegendGlyph,
3609
+ glyphSize: Math.max(0, toNumber(glyphStyle?.radius) ?? 4),
3610
+ collapseGroups: legendCollapseGroups,
3611
+ renderGlyph
3612
+ }), [
3613
+ withLegendGlyph,
3614
+ glyphStyle?.radius,
3615
+ legendCollapseGroups,
3616
+ renderGlyph
3617
+ ]), legendShape);
3618
+ const chartMetadata = (0, react.useMemo)(() => ({
3619
+ withGradientFill,
3620
+ smoothing,
3621
+ curveType,
3622
+ withStartGlyphs,
3623
+ withEndGlyphs,
3624
+ withLegendGlyph
3625
+ }), [
3626
+ withGradientFill,
3627
+ smoothing,
3628
+ curveType,
3629
+ withStartGlyphs,
3630
+ withEndGlyphs,
3631
+ withLegendGlyph
3632
+ ]);
3557
3633
  useChartRegistration({
3558
3634
  chartId,
3559
- legendItems: useChartLegendItems(dataSorted, (0, react.useMemo)(() => ({
3560
- withGlyph: withLegendGlyph,
3561
- glyphSize: Math.max(0, toNumber(glyphStyle?.radius) ?? 4),
3562
- collapseGroups: legendCollapseGroups,
3563
- renderGlyph
3564
- }), [
3565
- withLegendGlyph,
3566
- glyphStyle?.radius,
3567
- legendCollapseGroups,
3568
- renderGlyph
3569
- ]), legendShape),
3635
+ legendItems,
3570
3636
  chartType: "line",
3571
3637
  isDataValid,
3572
- metadata: (0, react.useMemo)(() => ({
3573
- withGradientFill,
3574
- smoothing,
3575
- curveType,
3576
- withStartGlyphs,
3577
- withEndGlyphs,
3578
- withLegendGlyph
3579
- }), [
3580
- withGradientFill,
3581
- smoothing,
3582
- curveType,
3583
- withStartGlyphs,
3584
- withEndGlyphs,
3585
- withLegendGlyph
3586
- ])
3638
+ metadata: chartMetadata
3587
3639
  });
3588
3640
  const prefersReducedMotion = usePrefersReducedMotion();
3589
3641
  const accessors = {
@@ -4003,26 +4055,28 @@ const AreaChartInternal = (0, react.forwardRef)(({ data, chartId: providedChartI
4003
4055
  const defaultMargin = useChartMargin(height, chartOptions, dataSorted, theme);
4004
4056
  const error = validateData$3(dataSorted);
4005
4057
  const isDataValid = !error;
4058
+ const legendItems = useChartLegendItems(dataSorted, (0, react.useMemo)(() => ({
4059
+ withGlyph: false,
4060
+ glyphSize: 0,
4061
+ collapseGroups: legend.collapseGroups ?? false
4062
+ }), [legend.collapseGroups]), legendShape);
4063
+ const chartMetadata = (0, react.useMemo)(() => ({
4064
+ stacked,
4065
+ stackOffset,
4066
+ smoothing,
4067
+ curveType
4068
+ }), [
4069
+ stacked,
4070
+ stackOffset,
4071
+ smoothing,
4072
+ curveType
4073
+ ]);
4006
4074
  useChartRegistration({
4007
4075
  chartId,
4008
- legendItems: useChartLegendItems(dataSorted, (0, react.useMemo)(() => ({
4009
- withGlyph: false,
4010
- glyphSize: 0,
4011
- collapseGroups: legend.collapseGroups ?? false
4012
- }), [legend.collapseGroups]), legendShape),
4076
+ legendItems,
4013
4077
  chartType: "area",
4014
4078
  isDataValid,
4015
- metadata: (0, react.useMemo)(() => ({
4016
- stacked,
4017
- stackOffset,
4018
- smoothing,
4019
- curveType
4020
- }), [
4021
- stacked,
4022
- stackOffset,
4023
- smoothing,
4024
- curveType
4025
- ])
4079
+ metadata: chartMetadata
4026
4080
  });
4027
4081
  const prefersReducedMotion = usePrefersReducedMotion();
4028
4082
  const animationEnabled = !!animation && !prefersReducedMotion;
@@ -4617,11 +4671,6 @@ function computeComparisonRect(params) {
4617
4671
  };
4618
4672
  }
4619
4673
  /**
4620
- * Fraction of each per-series step left as a gap between bars within a single tick.
4621
- * Larger = more space between adjacent series; the shadow spans `1 - COMPARISON_INNER_GAP` of the step.
4622
- */
4623
- const COMPARISON_INNER_GAP = .1;
4624
- /**
4625
4674
  * Upper clamp on the computed group padding, so bars can never collapse to zero width
4626
4675
  * even at very large `widthFactor` values.
4627
4676
  */
@@ -4709,7 +4758,7 @@ const renderTooltipRow = (label, value) => /* @__PURE__ */ (0, react_jsx_runtime
4709
4758
  className: bar_chart_module_default["bar-chart__tooltip-row"],
4710
4759
  children: (0, _wordpress_i18n.sprintf)((0, _wordpress_i18n.__)("%1$s: %2$s", "jetpack-charts"), label, value)
4711
4760
  });
4712
- const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, defaultHiddenSeries, animation, children, gap = "md" }) => {
4761
+ const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, defaultHiddenSeries, animation, children, gap = "md", onPointerDown, onPointerUp, onDatumActivate }) => {
4713
4762
  const legendInteractive = legend.interactive ?? false;
4714
4763
  const legendCollapseGroups = legend.collapseGroups ?? false;
4715
4764
  const horizontal = orientation === "horizontal";
@@ -4736,14 +4785,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
4736
4785
  const [selectedIndex, setSelectedIndex] = (0, react.useState)(void 0);
4737
4786
  const [isNavigating, setIsNavigating] = (0, react.useState)(false);
4738
4787
  const primarySeriesForNav = dataWithVisibleZeros.filter((s) => s.options?.type !== "comparison");
4739
- const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
4740
- selectedIndex,
4741
- setSelectedIndex,
4742
- isNavigating,
4743
- setIsNavigating,
4744
- chartRef,
4745
- totalPoints: Math.max(0, ...primarySeriesForNav.map((s) => s.data?.length || 0)) * primarySeriesForNav.length
4746
- });
4788
+ const totalPoints = Math.max(0, ...primarySeriesForNav.map((s) => s.data?.length || 0)) * primarySeriesForNav.length;
4747
4789
  const seriesWithVisibility = (0, react.useMemo)(() => dataWithVisibleZeros.map((series, index) => ({
4748
4790
  series,
4749
4791
  index,
@@ -4755,6 +4797,27 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
4755
4797
  const primaryEntries = (0, react.useMemo)(() => seriesWithVisibility.filter(({ isVisible, series }) => isVisible && series.options?.type !== "comparison"), [seriesWithVisibility]);
4756
4798
  const primaryKeys = (0, react.useMemo)(() => primaryEntries.map(({ series }) => series.label), [primaryEntries]);
4757
4799
  const primarySeries = (0, react.useMemo)(() => primaryEntries.map(({ series }) => series), [primaryEntries]);
4800
+ const activateSelectedBar = (0, react.useCallback)((index) => {
4801
+ const primaryCount = primaryEntries.length;
4802
+ if (!primaryCount) return;
4803
+ const dataPointIndex = Math.floor(index / primaryCount);
4804
+ const series = primaryEntries[index % primaryCount]?.series;
4805
+ const datum = series?.data[dataPointIndex];
4806
+ if (series && datum) onDatumActivate?.({
4807
+ datum,
4808
+ index: dataPointIndex,
4809
+ key: series.label
4810
+ });
4811
+ }, [primaryEntries, onDatumActivate]);
4812
+ const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
4813
+ selectedIndex,
4814
+ setSelectedIndex,
4815
+ isNavigating,
4816
+ setIsNavigating,
4817
+ chartRef,
4818
+ totalPoints,
4819
+ onActivate: activateSelectedBar
4820
+ });
4758
4821
  const comparisonEntries = (0, react.useMemo)(() => {
4759
4822
  const primaryByGroup = new Map(primaryEntries.map(({ series, index }) => [series.group, {
4760
4823
  label: series.label,
@@ -4791,7 +4854,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
4791
4854
  const groupPadding = (0, react.useMemo)(() => {
4792
4855
  const basePadding = chartOptions.barGroup.padding;
4793
4856
  if (!comparisonWidthFactor || comparisonWidthFactor <= 1) return basePadding;
4794
- const p = 1 - (1 - COMPARISON_INNER_GAP) / comparisonWidthFactor;
4857
+ const p = 1 - .9 / comparisonWidthFactor;
4795
4858
  return Math.min(Math.max(p, basePadding), MAX_GROUP_PADDING);
4796
4859
  }, [chartOptions.barGroup.padding, comparisonWidthFactor]);
4797
4860
  const { xScale, yScale } = (0, react.useMemo)(() => {
@@ -4929,15 +4992,17 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
4929
4992
  chartId
4930
4993
  ]);
4931
4994
  const error = validateData$2(dataSorted);
4995
+ const isDataValid = !error;
4996
+ const chartMetadata = (0, react.useMemo)(() => ({
4997
+ orientation,
4998
+ withPatterns
4999
+ }), [orientation, withPatterns]);
4932
5000
  useChartRegistration({
4933
5001
  chartId,
4934
5002
  legendItems,
4935
5003
  chartType: "bar",
4936
- isDataValid: !error,
4937
- metadata: (0, react.useMemo)(() => ({
4938
- orientation,
4939
- withPatterns
4940
- }), [orientation, withPatterns])
5004
+ isDataValid,
5005
+ metadata: chartMetadata
4941
5006
  });
4942
5007
  const prefersReducedMotion = usePrefersReducedMotion();
4943
5008
  if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -5002,6 +5067,8 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
5002
5067
  xScale,
5003
5068
  yScale,
5004
5069
  horizontal,
5070
+ onPointerDown,
5071
+ onPointerUp,
5005
5072
  pointerEventsDataKey: "nearest",
5006
5073
  children: [
5007
5074
  !allSeriesHidden && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.Grid, {
@@ -5157,6 +5224,25 @@ const BarListChartInternal = ({ data, width, height, options = {}, margin = {
5157
5224
  bottom: 0,
5158
5225
  top: 0
5159
5226
  }, ...rest }) => {
5227
+ const { getElementStyles } = useGlobalChartsContext();
5228
+ const tintedData = (0, react.useMemo)(() => {
5229
+ if (data.length > 1) return data;
5230
+ return data.map((series, index) => {
5231
+ if (series.options?.stroke) return series;
5232
+ const { color } = getElementStyles({
5233
+ data: series,
5234
+ index
5235
+ });
5236
+ if (!isValidHexColor(color)) return series;
5237
+ return {
5238
+ ...series,
5239
+ options: {
5240
+ ...series.options,
5241
+ stroke: lightenHexColor(color, .6)
5242
+ }
5243
+ };
5244
+ });
5245
+ }, [data, getElementStyles]);
5160
5246
  const chartOptions = (0, react.useMemo)(() => {
5161
5247
  const isMultiSeries = data.length > 1;
5162
5248
  const defaultYScale = {
@@ -5189,7 +5275,7 @@ const BarListChartInternal = ({ data, width, height, options = {}, margin = {
5189
5275
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BarChart, {
5190
5276
  orientation: "horizontal",
5191
5277
  gridVisibility: "none",
5192
- data,
5278
+ data: tintedData,
5193
5279
  width,
5194
5280
  height,
5195
5281
  margin,
@@ -5450,20 +5536,21 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
5450
5536
  })]
5451
5537
  });
5452
5538
  const isDataValid = Boolean(steps && steps.length > 0);
5539
+ const chartMetadata = (0, react.useMemo)(() => ({
5540
+ mainRate,
5541
+ changeIndicator,
5542
+ stepsCount: steps?.length || 0
5543
+ }), [
5544
+ mainRate,
5545
+ changeIndicator,
5546
+ steps?.length
5547
+ ]);
5453
5548
  useChartRegistration({
5454
5549
  chartId,
5455
5550
  legendItems: [],
5456
5551
  chartType: "conversion-funnel",
5457
5552
  isDataValid,
5458
- metadata: (0, react.useMemo)(() => ({
5459
- mainRate,
5460
- changeIndicator,
5461
- stepsCount: steps?.length || 0
5462
- }), [
5463
- mainRate,
5464
- changeIndicator,
5465
- steps?.length
5466
- ])
5553
+ metadata: chartMetadata
5467
5554
  });
5468
5555
  const prefersReducedMotion = usePrefersReducedMotion();
5469
5556
  if (!isDataValid) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_ui.Stack, {
@@ -6067,7 +6154,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
6067
6154
  });
6068
6155
  const chartBackgroundHex = normalizeColorToHex(theme.backgroundColor, scopeElement, resolveCssVariable);
6069
6156
  const primaryHex = normalizeColorToHex(primaryColorHex);
6070
- const cellHasLightText = (intensity) => isValidHexColor(primaryHex) && isValidHexColor(chartBackgroundHex) && prefersLightText(mixHexColors(primaryHex, chartBackgroundHex, 1 - (CELL_MIX_FLOOR + (1 - CELL_MIX_FLOOR) * intensity)));
6157
+ const cellHasLightText = (intensity) => isValidHexColor(primaryHex) && isValidHexColor(chartBackgroundHex) && prefersLightText(mixHexColors(primaryHex, chartBackgroundHex, 1 - (CELL_MIX_FLOOR + .85 * intensity)));
6071
6158
  const extent = (0, react.useMemo)(() => getValueExtent(data), [data]);
6072
6159
  const heatmapContext = (0, react.useMemo)(() => ({
6073
6160
  extent,
@@ -6686,7 +6773,7 @@ var require_dist = /* @__PURE__ */ __commonJSMin(((exports) => {
6686
6773
  tslib_1.__exportStar(require_dist$1(), exports);
6687
6774
  }));
6688
6775
  //#endregion
6689
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/utils/hooks/use-update-effect.mjs
6776
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/utils/hooks/use-update-effect.mjs
6690
6777
  function useUpdateEffect(effect, deps) {
6691
6778
  const mountedRef = (0, react.useRef)(false);
6692
6779
  (0, react.useEffect)(() => {
@@ -6718,10 +6805,11 @@ var StyleSheet = /*#__PURE__*/ function() {
6718
6805
  var _this = this;
6719
6806
  this._insertTag = function(tag) {
6720
6807
  var before;
6721
- if (_this.tags.length === 0) if (_this.insertionPoint) before = _this.insertionPoint.nextSibling;
6722
- else if (_this.prepend) before = _this.container.firstChild;
6723
- else before = _this.before;
6724
- else before = _this.tags[_this.tags.length - 1].nextSibling;
6808
+ if (_this.tags.length === 0) {
6809
+ if (_this.insertionPoint) before = _this.insertionPoint.nextSibling;
6810
+ else if (_this.prepend) before = _this.container.firstChild;
6811
+ else before = _this.before;
6812
+ } else before = _this.tags[_this.tags.length - 1].nextSibling;
6725
6813
  _this.container.insertBefore(tag, before);
6726
6814
  _this.tags.push(tag);
6727
6815
  };
@@ -7040,9 +7128,7 @@ function delimiter(type) {
7040
7128
  case 40:
7041
7129
  if (type === 41) delimiter(type);
7042
7130
  break;
7043
- case 92:
7044
- next();
7045
- break;
7131
+ case 92: next();
7046
7132
  }
7047
7133
  return position;
7048
7134
  }
@@ -8065,14 +8151,12 @@ function handleInterpolation(mergedProps, registered, interpolation) {
8065
8151
  return serializedStyles.styles + ";";
8066
8152
  }
8067
8153
  return createStringFromObject(mergedProps, registered, interpolation);
8068
- case "function":
8069
- if (mergedProps !== void 0) {
8070
- var previousCursor = cursor;
8071
- var result = interpolation(mergedProps);
8072
- cursor = previousCursor;
8073
- return handleInterpolation(mergedProps, registered, result);
8074
- }
8075
- break;
8154
+ case "function": if (mergedProps !== void 0) {
8155
+ var previousCursor = cursor;
8156
+ var result = interpolation(mergedProps);
8157
+ cursor = previousCursor;
8158
+ return handleInterpolation(mergedProps, registered, result);
8159
+ }
8076
8160
  }
8077
8161
  var asString = interpolation;
8078
8162
  if (registered == null) return asString;
@@ -8327,7 +8411,7 @@ _createEmotion.css;
8327
8411
  _createEmotion.sheet;
8328
8412
  _createEmotion.cache;
8329
8413
  //#endregion
8330
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/utils/hooks/use-cx.mjs
8414
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/utils/hooks/use-cx.mjs
8331
8415
  var isSerializedStyles = (o) => typeof o !== "undefined" && o !== null && ["name", "styles"].every((p) => typeof o[p] !== "undefined");
8332
8416
  var useCx = () => {
8333
8417
  const cache = __unsafe_useEmotionCache();
@@ -8434,7 +8518,7 @@ function memize(fn, options) {
8434
8518
  return memoized;
8435
8519
  }
8436
8520
  //#endregion
8437
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/utils/colors-values.mjs
8521
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/utils/colors-values.mjs
8438
8522
  var white = "#fff";
8439
8523
  var GRAY = {
8440
8524
  900: "#1e1e1e",
@@ -8513,7 +8597,7 @@ var COLORS = Object.freeze({
8513
8597
  ui: UI
8514
8598
  });
8515
8599
  //#endregion
8516
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/utils/config-values.mjs
8600
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/utils/config-values.mjs
8517
8601
  var CONTROL_HEIGHT = "36px";
8518
8602
  var CONTROL_PROPS = {
8519
8603
  controlPaddingX: 12,
@@ -8618,10 +8702,10 @@ var require_es6 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
8618
8702
  };
8619
8703
  }));
8620
8704
  //#endregion
8621
- //#region ../../../node_modules/.pnpm/@wordpress+warning@3.52.0/node_modules/@wordpress/warning/build-module/utils.mjs
8705
+ //#region ../../../node_modules/.pnpm/@wordpress+warning@3.53.0/node_modules/@wordpress/warning/build-module/utils.mjs
8622
8706
  var logged = /* @__PURE__ */ new Set();
8623
8707
  //#endregion
8624
- //#region ../../../node_modules/.pnpm/@wordpress+warning@3.52.0/node_modules/@wordpress/warning/build-module/index.mjs
8708
+ //#region ../../../node_modules/.pnpm/@wordpress+warning@3.53.0/node_modules/@wordpress/warning/build-module/index.mjs
8625
8709
  function isDev() {
8626
8710
  return globalThis.SCRIPT_DEBUG === true;
8627
8711
  }
@@ -8635,7 +8719,7 @@ function warning(message) {
8635
8719
  logged.add(message);
8636
8720
  }
8637
8721
  //#endregion
8638
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/context/context-system-provider.mjs
8722
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/context/context-system-provider.mjs
8639
8723
  var import_es6 = /* @__PURE__ */ __toESM(require_es6(), 1);
8640
8724
  var ComponentsContext = (0, react.createContext)(
8641
8725
  /** @type {Record<string, any>} */
@@ -8662,19 +8746,19 @@ var BaseContextSystemProvider = ({ children, value }) => {
8662
8746
  };
8663
8747
  (0, react.memo)(BaseContextSystemProvider);
8664
8748
  //#endregion
8665
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/context/constants.mjs
8749
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/context/constants.mjs
8666
8750
  var COMPONENT_NAMESPACE = "data-wp-component";
8667
8751
  var CONNECTED_NAMESPACE = "data-wp-c16t";
8668
8752
  var CONNECT_STATIC_NAMESPACE = "__contextSystemKey__";
8669
8753
  //#endregion
8670
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/context/get-styled-class-name-from-key.mjs
8754
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/context/get-styled-class-name-from-key.mjs
8671
8755
  var import_dist = require_dist();
8672
8756
  function getStyledClassName(namespace) {
8673
8757
  return `components-${(0, import_dist.paramCase)(namespace)}`;
8674
8758
  }
8675
8759
  var getStyledClassNameFromKey = memize(getStyledClassName);
8676
8760
  //#endregion
8677
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/context/context-connect.mjs
8761
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/context/context-connect.mjs
8678
8762
  function contextConnect(Component, namespace) {
8679
8763
  return _contextConnect(Component, namespace, { forwardsRef: true });
8680
8764
  }
@@ -8691,7 +8775,7 @@ function _contextConnect(Component, namespace, options) {
8691
8775
  });
8692
8776
  }
8693
8777
  //#endregion
8694
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/context/utils.mjs
8778
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/context/utils.mjs
8695
8779
  function getNamespace(componentName) {
8696
8780
  return { [COMPONENT_NAMESPACE]: componentName };
8697
8781
  }
@@ -8699,7 +8783,7 @@ function getConnectedNamespace() {
8699
8783
  return { [CONNECTED_NAMESPACE]: true };
8700
8784
  }
8701
8785
  //#endregion
8702
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/context/use-context-system.mjs
8786
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/context/use-context-system.mjs
8703
8787
  function useContextSystem(props, namespace) {
8704
8788
  const contextSystemProps = useComponentsContext();
8705
8789
  if (typeof namespace === "undefined") globalThis.SCRIPT_DEBUG === true && warning("useContextSystem: Please provide a namespace");
@@ -8719,7 +8803,7 @@ function useContextSystem(props, namespace) {
8719
8803
  return finalComponentProps;
8720
8804
  }
8721
8805
  //#endregion
8722
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/visually-hidden/styles.mjs
8806
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/visually-hidden/styles.mjs
8723
8807
  var visuallyHidden = {
8724
8808
  border: 0,
8725
8809
  clip: "rect(1px, 1px, 1px, 1px)",
@@ -8735,7 +8819,7 @@ var visuallyHidden = {
8735
8819
  wordBreak: "normal"
8736
8820
  };
8737
8821
  //#endregion
8738
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/utils/polymorphic-element.mjs
8822
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/utils/polymorphic-element.mjs
8739
8823
  var customAttributeRegExp = /^(data|aria|x)-/i;
8740
8824
  var eventHandlerRegExp = /^on[A-Z]/;
8741
8825
  var svgElementNames = new Set(`animate animateMotion animateTransform circle clipPath defs desc ellipse
@@ -8817,14 +8901,15 @@ function filterIntrinsicElementProps(props, element) {
8817
8901
  }
8818
8902
  function UnforwardedPolymorphicElement({ as, ...props }, ref) {
8819
8903
  const Element = as || "div";
8904
+ const forwardedProps = typeof Element === "string" ? filterIntrinsicElementProps(props, Element) : props;
8820
8905
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Element, {
8821
8906
  ref,
8822
- ...typeof Element === "string" ? filterIntrinsicElementProps(props, Element) : props
8907
+ ...forwardedProps
8823
8908
  });
8824
8909
  }
8825
8910
  var PolymorphicElement = (0, react.forwardRef)(UnforwardedPolymorphicElement);
8826
8911
  //#endregion
8827
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/view/component.mjs
8912
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/view/component.mjs
8828
8913
  function UnforwardedView({ css, ...restProps }, ref) {
8829
8914
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PolymorphicElement, {
8830
8915
  ref,
@@ -8833,7 +8918,7 @@ function UnforwardedView({ css, ...restProps }, ref) {
8833
8918
  }
8834
8919
  var component_default$2 = Object.assign((0, react.forwardRef)(UnforwardedView), { selector: ".components-view" });
8835
8920
  //#endregion
8836
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/visually-hidden/component.mjs
8921
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/visually-hidden/component.mjs
8837
8922
  function UnconnectedVisuallyHidden(props, forwardedRef) {
8838
8923
  const { style: styleProp, ...contextProps } = useContextSystem(props, "VisuallyHidden");
8839
8924
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(component_default$2, {
@@ -8848,7 +8933,7 @@ function UnconnectedVisuallyHidden(props, forwardedRef) {
8848
8933
  }
8849
8934
  var component_default$1 = contextConnect(UnconnectedVisuallyHidden, "VisuallyHidden");
8850
8935
  //#endregion
8851
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/utils/use-responsive-value.mjs
8936
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/utils/use-responsive-value.mjs
8852
8937
  var breakpoints = [
8853
8938
  "40em",
8854
8939
  "52em",
@@ -8882,7 +8967,7 @@ function useResponsiveValue(values, options = {}) {
8882
8967
  return array[index >= array.length ? array.length - 1 : index];
8883
8968
  }
8884
8969
  //#endregion
8885
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/grid/utils.mjs
8970
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/grid/utils.mjs
8886
8971
  var ALIGNMENTS = {
8887
8972
  bottom: {
8888
8973
  alignItems: "flex-end",
@@ -8930,7 +9015,7 @@ function getAlignmentProps(alignment) {
8930
9015
  return alignment ? ALIGNMENTS[alignment] : {};
8931
9016
  }
8932
9017
  //#endregion
8933
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/grid/hook.mjs
9018
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/grid/hook.mjs
8934
9019
  function useGrid(props) {
8935
9020
  const { align, alignment, className, columnGap, columns = 2, gap = 3, isInline = false, justify, rowGap, rows, templateColumns, templateRows, ...otherProps } = useContextSystem(props, "Grid");
8936
9021
  const column = useResponsiveValue(Array.isArray(columns) ? columns : [columns]);
@@ -8972,10 +9057,11 @@ function useGrid(props) {
8972
9057
  };
8973
9058
  }
8974
9059
  //#endregion
8975
- //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react@18.3.28_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@wordpress/components/build-module/grid/component.mjs
9060
+ //#region ../../../node_modules/.pnpm/@wordpress+components@37.0.0_@types+react-dom@18.3.7_@types+react@18.3.31__@types+react_e283446b3cbc213906bb0d97b3dd78c5/node_modules/@wordpress/components/build-module/grid/component.mjs
8976
9061
  function UnconnectedGrid(props, forwardedRef) {
9062
+ const gridProps = useGrid(props);
8977
9063
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(component_default$2, {
8978
- ...useGrid(props),
9064
+ ...gridProps,
8979
9065
  ref: forwardedRef
8980
9066
  });
8981
9067
  }
@@ -9287,15 +9373,17 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
9287
9373
  withComparison,
9288
9374
  withOverlayLabel
9289
9375
  ]);
9376
+ const isDataValid = Boolean(data && data.length > 0);
9377
+ const chartMetadata = (0, react.useMemo)(() => ({
9378
+ withComparison,
9379
+ withOverlayLabel
9380
+ }), [withComparison, withOverlayLabel]);
9290
9381
  useChartRegistration({
9291
9382
  chartId,
9292
9383
  legendItems,
9293
9384
  chartType: "leaderboard",
9294
- isDataValid: Boolean(data && data.length > 0),
9295
- metadata: (0, react.useMemo)(() => ({
9296
- withComparison,
9297
- withOverlayLabel
9298
- }), [withComparison, withOverlayLabel])
9385
+ isDataValid,
9386
+ metadata: chartMetadata
9299
9387
  });
9300
9388
  const prefersReducedMotion = usePrefersReducedMotion();
9301
9389
  const { contentRef, fittedCount, isMeasurable } = useFittedRowCount(fitRows && !allSeriesHidden, data?.length ?? 0, data);
@@ -9550,8 +9638,9 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
9550
9638
  hideTooltip();
9551
9639
  }, [withTooltips, hideTooltip]);
9552
9640
  const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
9641
+ const dataWithPercentages = useDataWithPercentages(data);
9553
9642
  const { visibleData, allSegmentsHidden, legendData } = useLegendVisibilityData({
9554
- data: useDataWithPercentages(data),
9643
+ data: dataWithPercentages,
9555
9644
  chartId,
9556
9645
  isSeriesVisible
9557
9646
  });
@@ -9561,20 +9650,21 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
9561
9650
  }), [legendValueDisplay]));
9562
9651
  const { isValid, message } = validateData$1(data);
9563
9652
  const { svgChildren, htmlChildren, legendChildren, otherChildren } = useChartChildren(children, "PieChart");
9653
+ const chartMetadata = (0, react.useMemo)(() => ({
9654
+ thickness,
9655
+ gapScale,
9656
+ cornerScale
9657
+ }), [
9658
+ thickness,
9659
+ gapScale,
9660
+ cornerScale
9661
+ ]);
9564
9662
  useChartRegistration({
9565
9663
  chartId,
9566
9664
  legendItems,
9567
9665
  chartType: "pie",
9568
9666
  isDataValid: isValid,
9569
- metadata: (0, react.useMemo)(() => ({
9570
- thickness,
9571
- gapScale,
9572
- cornerScale
9573
- }), [
9574
- thickness,
9575
- gapScale,
9576
- cornerScale
9577
- ])
9667
+ metadata: chartMetadata
9578
9668
  });
9579
9669
  const prefersReducedMotion = usePrefersReducedMotion();
9580
9670
  if (!isValid) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -9703,14 +9793,12 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
9703
9793
  }
9704
9794
  const svgLabelSmall = providerTheme.svgLabelSmall;
9705
9795
  const fontSize = resolveFontSize(svgLabelSmall?.fontSize) ?? 12;
9706
- const estimatedTextWidth = (0, _visx_text.getStringWidth)(arc.data.label, {
9796
+ const backgroundWidth = (0, _visx_text.getStringWidth)(arc.data.label, {
9707
9797
  fontSize,
9708
9798
  fontFamily: svgLabelSmall?.fontFamily,
9709
9799
  fontWeight: svgLabelSmall?.fontWeight
9710
- });
9711
- const labelPadding = 6;
9712
- const backgroundWidth = estimatedTextWidth + labelPadding * 2;
9713
- const backgroundHeight = fontSize + labelPadding * 2;
9800
+ }) + 12;
9801
+ const backgroundHeight = fontSize + 12;
9714
9802
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
9715
9803
  ...groupProps,
9716
9804
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { ...pathProps }), showLabels && hasSpaceForLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [providerTheme.labelBackgroundColor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
@@ -9842,8 +9930,9 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
9842
9930
  }, [handleMouseMove]);
9843
9931
  const { isValid, message } = validateData(data);
9844
9932
  const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
9933
+ const dataWithPercentages = useDataWithPercentages(data);
9845
9934
  const { visibleData, allSegmentsHidden, legendData } = useLegendVisibilityData({
9846
- data: useDataWithPercentages(data),
9935
+ data: dataWithPercentages,
9847
9936
  chartId,
9848
9937
  isSeriesVisible
9849
9938
  });
@@ -9860,15 +9949,16 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
9860
9949
  legendValueDisplay
9861
9950
  }), [legendValueDisplay]));
9862
9951
  const { svgChildren, htmlChildren, legendChildren, otherChildren } = useChartChildren(children, "PieSemiCircleChart");
9952
+ const chartMetadata = (0, react.useMemo)(() => ({
9953
+ thickness,
9954
+ clockwise
9955
+ }), [thickness, clockwise]);
9863
9956
  useChartRegistration({
9864
9957
  chartId,
9865
9958
  legendItems,
9866
9959
  chartType: "pie-semi-circle",
9867
9960
  isDataValid: isValid,
9868
- metadata: (0, react.useMemo)(() => ({
9869
- thickness,
9870
- clockwise
9871
- }), [thickness, clockwise])
9961
+ metadata: chartMetadata
9872
9962
  });
9873
9963
  const prefersReducedMotion = usePrefersReducedMotion();
9874
9964
  const effectiveWidth = propWidth || DEFAULT_WIDTH$1;
@@ -10059,6 +10149,7 @@ const transformToSeriesData = (data, color, strokeWidth) => {
10059
10149
  };
10060
10150
  const SparklineComponent = (0, react.forwardRef)(({ data, width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT, color, strokeWidth: strokeWidthProp, withGradientFill = true, gradient, className, chartId, margin: marginProp, animation }, ref) => {
10061
10151
  const theme = useGlobalChartsTheme();
10152
+ const chartsContext = (0, react.useContext)(GlobalChartsContext);
10062
10153
  const themeStrokeWidth = theme.sparkline?.strokeWidth ?? 1.5;
10063
10154
  const strokeWidth = strokeWidthProp ?? themeStrokeWidth;
10064
10155
  const seriesData = (0, react.useMemo)(() => {
@@ -10112,7 +10203,7 @@ const SparklineComponent = (0, react.forwardRef)(({ data, width = DEFAULT_WIDTH,
10112
10203
  if (data.length === 1) {
10113
10204
  const cx = width / 2;
10114
10205
  const cy = height / 2;
10115
- const resolvedColor = color || "#000000";
10206
+ const resolvedColor = color || chartsContext?.getElementStyles({ index: 0 }).color || "#000000";
10116
10207
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
10117
10208
  ref,
10118
10209
  className: (0, clsx.default)("sparkline", sparkline_module_default.sparkline, sparkline_module_default["sparkline--single-point"], className),
@@ -10215,8 +10306,9 @@ const Icon = ({ direction }) => {
10215
10306
  */
10216
10307
  function TrendIndicator({ direction, value, className, style, showIcon = true }) {
10217
10308
  const ariaLabel = `${DIRECTION_LABELS[direction]}: ${value}`;
10309
+ const standaloneScopeClass = useStandaloneScopeClass();
10218
10310
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
10219
- className: (0, clsx.default)(useStandaloneScopeClass(), trend_indicator_module_default["trend-indicator"], trend_indicator_module_default[`trend-indicator--${direction}`], className),
10311
+ className: (0, clsx.default)(standaloneScopeClass, trend_indicator_module_default["trend-indicator"], trend_indicator_module_default[`trend-indicator--${direction}`], className),
10220
10312
  style,
10221
10313
  "aria-label": ariaLabel,
10222
10314
  children: [showIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { direction }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {