@automattic/charts 4.12.0 → 4.13.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 (39) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/index.cjs +641 -636
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +40 -12
  5. package/dist/index.d.cts +26 -121
  6. package/dist/index.d.ts +26 -121
  7. package/dist/index.js +630 -613
  8. package/dist/index.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/charts/area-chart/area-chart.tsx +16 -6
  11. package/src/charts/area-chart/test/area-chart.test.tsx +42 -9
  12. package/src/charts/bar-chart/bar-chart.tsx +17 -12
  13. package/src/charts/bar-chart/private/index.ts +1 -1
  14. package/src/charts/bar-chart/private/slot-tooltip-members.tsx +4 -5
  15. package/src/charts/bar-chart/private/use-bar-stops.ts +1 -3
  16. package/src/charts/bar-chart/private/use-overlap-slots.ts +35 -16
  17. package/src/charts/bar-chart/test/bar-chart.test.tsx +115 -0
  18. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss +24 -11
  19. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx +235 -182
  20. package/src/charts/conversion-funnel-chart/index.ts +2 -0
  21. package/src/charts/conversion-funnel-chart/private/index.ts +1 -0
  22. package/src/charts/conversion-funnel-chart/private/use-funnel-selection.ts +9 -47
  23. package/src/charts/conversion-funnel-chart/private/use-roving-step-focus.ts +83 -0
  24. package/src/charts/conversion-funnel-chart/test/conversion-funnel-chart.test.tsx +312 -92
  25. package/src/charts/conversion-funnel-chart/test/use-funnel-selection.test.ts +23 -188
  26. package/src/charts/conversion-funnel-chart/types.ts +22 -0
  27. package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +41 -1
  28. package/src/charts/leaderboard-chart/leaderboard-chart.tsx +101 -30
  29. package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +47 -0
  30. package/src/charts/line-chart/line-chart.tsx +10 -8
  31. package/src/charts/line-chart/test/line-chart.test.tsx +75 -0
  32. package/src/components/tooltip/private/at-nearest-date.ts +49 -0
  33. package/src/components/tooltip/private/keyboard-stops.ts +67 -0
  34. package/src/components/tooltip/private/xy-chart-tooltip-overlay.tsx +10 -2
  35. package/src/components/tooltip/test/keyboard-stops.test.ts +36 -0
  36. package/src/components/tooltip/test/xy-chart-tooltip.test.tsx +135 -1
  37. package/src/components/tooltip/xy-chart-tooltip.tsx +8 -12
  38. package/src/index.ts +2 -0
  39. package/src/types.ts +4 -3
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { getStringWidth as getStringWidth$1 } from "./visx/text/index.js";
2
2
  import { formatNumber, formatNumberCompact } from "@automattic/number-formatters";
3
3
  import { AnimatedAreaSeries, AnimatedAreaStack, AreaSeries, Axis, BarGroup, BarSeries, DataContext, GlyphSeries, Grid, TooltipContext, XYChart, buildChartTheme, useEventEmitter } from "@visx/xychart";
4
- import { __, _x, sprintf } from "@wordpress/i18n";
4
+ import { __, _n, _x, sprintf } from "@wordpress/i18n";
5
5
  import clsx from "clsx";
6
6
  import * as React from "react";
7
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";
@@ -30,7 +30,7 @@ import { __assign } from "tslib";
30
30
  import "@babel/runtime/helpers/esm/extends";
31
31
  import { Icon, chevronRight } from "@wordpress/icons";
32
32
  import { arc, pie } from "@visx/shape";
33
- //#region \0rolldown/runtime.js
33
+ // \0rolldown/runtime.js
34
34
  var __create = Object.create;
35
35
  var __defProp = Object.defineProperty;
36
36
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -52,26 +52,22 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
52
52
  value: mod,
53
53
  enumerable: true
54
54
  }) : target, mod));
55
- //#endregion
56
- //#region src/charts/private/chart-instance-context/chart-instance-context.ts
55
+ // src/charts/private/chart-instance-context/chart-instance-context.ts
57
56
  const ChartInstanceContext = createContext(null);
58
- //#endregion
59
- //#region src/charts/private/chart-instance-context/use-chart-instance-context.ts
57
+ // src/charts/private/chart-instance-context/use-chart-instance-context.ts
60
58
  const useChartInstanceContext = () => {
61
59
  const context = useContext(ChartInstanceContext);
62
60
  if (!context) throw new Error("useChartInstanceContext must be used within a Chart component");
63
61
  return context;
64
62
  };
65
- //#endregion
66
- //#region src/styles/chart-scope-class.ts
63
+ // src/styles/chart-scope-class.ts
67
64
  /**
68
65
  * Stable class that carries the `--a8c-charts-*` catalog. Applied to the `GlobalChartsProvider` wrapper, to portal-rendered surfaces (which sit outside the provider tree), and to standalone components when no provider is above them.
69
66
  *
70
67
  * Deliberately unhashed: consumers are documented as being able to target it to override a token on the provider element.
71
68
  */
72
69
  const CHART_SCOPE_CLASS = "a8c-charts-scope";
73
- //#endregion
74
- //#region src/utils/create-composition.ts
70
+ // src/utils/create-composition.ts
75
71
  /**
76
72
  * Utility function to create chart components with composition API.
77
73
  *
@@ -85,8 +81,7 @@ const CHART_SCOPE_CLASS = "a8c-charts-scope";
85
81
  function attachSubComponents(Chart, subComponents) {
86
82
  return Object.assign(Chart, subComponents);
87
83
  }
88
- //#endregion
89
- //#region src/utils/warn-once.ts
84
+ // src/utils/warn-once.ts
90
85
  const warned = /* @__PURE__ */ new Set();
91
86
  /**
92
87
  * Warns about a host-supplied value once per process, and never in production.
@@ -99,8 +94,7 @@ const warnOnce = (key, message) => {
99
94
  warned.add(key);
100
95
  console.warn(`[Charts] ${message}`);
101
96
  };
102
- //#endregion
103
- //#region src/utils/date-parsing.ts
97
+ // src/utils/date-parsing.ts
104
98
  /**
105
99
  * @file Date parsing: a naive string is dated in a supplied IANA zone, or the runtime's own
106
100
  *
@@ -195,8 +189,7 @@ const parseAsLocalDate = (dateString, timeZone) => {
195
189
  }
196
190
  return /* @__PURE__ */ new Date(NaN);
197
191
  };
198
- //#endregion
199
- //#region src/utils/bucket-info.ts
192
+ // src/utils/bucket-info.ts
200
193
  const getInstant = (point) => {
201
194
  if (!point) return;
202
195
  if ("date" in point && point.date) return point.date.getTime();
@@ -228,8 +221,7 @@ const getBucketInfo = (data, tickResolution) => ({
228
221
  bucket: tickResolution ?? getBucketResolution(data),
229
222
  displayResolution: getBucketResolution(data, tickResolution)
230
223
  });
231
- //#endregion
232
- //#region src/utils/format-metric-value.ts
224
+ // src/utils/format-metric-value.ts
233
225
  /**
234
226
  * Format a numeric metric value based on type, precision and scale.
235
227
  * Supports currency, number and percentage, using `@automattic/number-formatters`.
@@ -278,8 +270,7 @@ const formatMetricValue = (value, type = "number", { decimals, useMultipliers =
278
270
  });
279
271
  }
280
272
  };
281
- //#endregion
282
- //#region src/utils/format-percentage.ts
273
+ // src/utils/format-percentage.ts
283
274
  /**
284
275
  * Format a percentage value with smart decimal handling.
285
276
  * Uses `@automattic/number-formatters` for consistent formatting.
@@ -295,8 +286,7 @@ const formatPercentage = (value) => {
295
286
  maximumFractionDigits: 2
296
287
  } });
297
288
  };
298
- //#endregion
299
- //#region src/utils/get-edge-tick-widths.ts
289
+ // src/utils/get-edge-tick-widths.ts
300
290
  /**
301
291
  * Rendered widths of the first and last tick labels on an axis.
302
292
  *
@@ -320,8 +310,7 @@ const getEdgeTickWidths = (ticks, formatTick, labelStyle) => {
320
310
  last: getStringWidth(label(ticks[lastIndex], lastIndex), labelStyle) ?? 0
321
311
  };
322
312
  };
323
- //#endregion
324
- //#region src/utils/get-longest-tick-width.ts
313
+ // src/utils/get-longest-tick-width.ts
325
314
  /**
326
315
  * Returns the width of the longest tick.
327
316
  *
@@ -335,8 +324,7 @@ const getLongestTickWidth = (ticks, formatTick, labelStyle) => {
335
324
  const longestTick = formattedTicks.reduce((longest, current) => longest.length >= current.length ? longest : current, formattedTicks[0]);
336
325
  return getStringWidth(longestTick, labelStyle);
337
326
  };
338
- //#endregion
339
- //#region src/utils/get-styles.ts
327
+ // src/utils/get-styles.ts
340
328
  /**
341
329
  * Utility function to get consolidated line styles for a series
342
330
  * This consolidates the logic used by both LineChart and Legend components
@@ -389,19 +377,16 @@ function getItemShapeStyles(series, index, theme, legendShape) {
389
377
  ...barShapeStyles
390
378
  };
391
379
  }
392
- //#endregion
393
- //#region src/utils/is-safari.ts
380
+ // src/utils/is-safari.ts
394
381
  const isSafari = () => {
395
382
  if (typeof navigator !== "undefined" && navigator.userAgent) return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
396
383
  return false;
397
384
  };
398
- //#endregion
399
- //#region src/utils/merge-themes.ts
385
+ // src/utils/merge-themes.ts
400
386
  function mergeThemes(baseTheme, overrideTheme) {
401
387
  return deepmerge(baseTheme, overrideTheme, { arrayMerge: (_destinationArray, sourceArray) => sourceArray });
402
388
  }
403
- //#endregion
404
- //#region src/utils/color-utils.ts
389
+ // src/utils/color-utils.ts
405
390
  /**
406
391
  * Check if a value is a valid 6-digit hex color
407
392
  * @param hex - The value to check
@@ -568,8 +553,7 @@ const prefersLightText = (backgroundHex) => {
568
553
  if (!isValidHexColor(backgroundHex)) return false;
569
554
  return relativeLuminance(backgroundHex) <= .179;
570
555
  };
571
- //#endregion
572
- //#region src/utils/resolve-css-var.ts
556
+ // src/utils/resolve-css-var.ts
573
557
  /**
574
558
  * Pattern for valid CSS custom property names (e.g., '--my-color', '--jp-gray-10')
575
559
  */
@@ -666,8 +650,7 @@ function readCustomProperty(varName, styles) {
666
650
  return null;
667
651
  }
668
652
  }
669
- //#endregion
670
- //#region src/utils/resolve-font-size.ts
653
+ // src/utils/resolve-font-size.ts
671
654
  const toFontSize = (size) => Number.isFinite(size) && size >= 0 ? size : void 0;
672
655
  /**
673
656
  * Resolve a theme `fontSize` value into a plain number suitable for
@@ -694,8 +677,7 @@ const resolveFontSize = (val) => {
694
677
  return match ? toFontSize(parseFloat(match[1])) : void 0;
695
678
  }
696
679
  };
697
- //#endregion
698
- //#region src/utils/date-formatting.ts
680
+ // src/utils/date-formatting.ts
699
681
  const formatters = /* @__PURE__ */ new Map();
700
682
  const getFormatter$1 = (options, { locale, timeZone }) => {
701
683
  const key = `${locale ?? ""}|${timeZone ?? ""}|${JSON.stringify(options)}`;
@@ -794,8 +776,7 @@ const createZonedClock = (timeZone) => {
794
776
  };
795
777
  };
796
778
  };
797
- //#endregion
798
- //#region src/providers/chart-scope/chart-scope-context.ts
779
+ // src/providers/chart-scope/chart-scope-context.ts
799
780
  /**
800
781
  * The nearest chart element, published so JS token resolution reads the same CSS cascade that paints the chart's own colours.
801
782
  *
@@ -812,8 +793,7 @@ const seriesRole = (slot) => `--a8c-charts-color-series-${slot}`;
812
793
  const SERIES_SLOT_1_FALLBACK = "#3858e9";
813
794
  /** The catalog pointer for every slot, in slot order. */
814
795
  const SERIES_PALETTE_POINTERS = Array.from({ length: 5 }, (_, index) => index === 0 ? `var(${seriesRole(1)}, ${SERIES_SLOT_1_FALLBACK})` : `var(${seriesRole(index + 1)})`);
815
- //#endregion
816
- //#region src/providers/chart-context/private/catalog-pointers.ts
796
+ // src/providers/chart-context/private/catalog-pointers.ts
817
797
  /** Terminal literals the provider also generates from before its first read, so SSR and the first client render agree. */
818
798
  const BACKGROUND_FALLBACK = "#ffffff";
819
799
  const LABEL_FALLBACK = "#1e1e1e";
@@ -853,8 +833,7 @@ const ANNOTATION_POINTERS = {
853
833
  radius: 5
854
834
  }
855
835
  };
856
- //#endregion
857
- //#region src/providers/chart-context/private/perceptual-color.ts
836
+ // src/providers/chart-context/private/perceptual-color.ts
858
837
  const DEUTERANOPIA = [
859
838
  .367322,
860
839
  .860646,
@@ -1260,16 +1239,14 @@ const buildPaletteGenerator = (normalizedSeeds, background, labelColors) => {
1260
1239
  return palette[index].hex;
1261
1240
  };
1262
1241
  };
1263
- //#endregion
1264
- //#region src/providers/chart-context/private/resolve-opaque-hex.ts
1242
+ // src/providers/chart-context/private/resolve-opaque-hex.ts
1265
1243
  const resolveOpaqueHex = (pointer, resolve) => {
1266
1244
  const raw = resolve(pointer);
1267
1245
  if (!raw || color(raw)?.opacity !== 1) return null;
1268
1246
  const hex = normalizeColorToHex(raw);
1269
1247
  return isValidHexColor(hex) ? hex : null;
1270
1248
  };
1271
- //#endregion
1272
- //#region src/providers/chart-context/themes.ts
1249
+ // src/providers/chart-context/themes.ts
1273
1250
  /**
1274
1251
  * Default theme configuration: the shape and spacing a consumer can override.
1275
1252
  *
@@ -1312,8 +1289,7 @@ const defaultTheme = {
1312
1289
  groupGap: 24
1313
1290
  }
1314
1291
  };
1315
- //#endregion
1316
- //#region src/providers/chart-context/global-charts-provider.tsx
1292
+ // src/providers/chart-context/global-charts-provider.tsx
1317
1293
  const PLACEHOLDER_LABEL_COLORS = [LABEL_FALLBACK, LABEL_INVERSE_FALLBACK];
1318
1294
  const GlobalChartsContext = createContext(null);
1319
1295
  const GlobalChartsProvider = ({ children, theme, locale, timeZone }) => {
@@ -1494,21 +1470,18 @@ const GlobalChartsProvider = ({ children, theme, locale, timeZone }) => {
1494
1470
  })
1495
1471
  });
1496
1472
  };
1497
- //#endregion
1498
- //#region src/providers/chart-context/hooks/use-global-charts-context.ts
1473
+ // src/providers/chart-context/hooks/use-global-charts-context.ts
1499
1474
  const useGlobalChartsContext = () => {
1500
1475
  const context = useContext(GlobalChartsContext);
1501
1476
  if (!context) throw new Error("useGlobalChartsContext must be used within a GlobalChartsProvider");
1502
1477
  return context;
1503
1478
  };
1504
- //#endregion
1505
- //#region src/providers/chart-context/hooks/use-chart-id.ts
1479
+ // src/providers/chart-context/hooks/use-chart-id.ts
1506
1480
  const useChartId = (providedId) => {
1507
1481
  const generatedId = useId();
1508
1482
  return providedId || generatedId;
1509
1483
  };
1510
- //#endregion
1511
- //#region src/hooks/use-deep-memo.ts
1484
+ // src/hooks/use-deep-memo.ts
1512
1485
  var import_fast_deep_equal = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
1513
1486
  module.exports = function equal(a, b) {
1514
1487
  if (a === b) return true;
@@ -1549,16 +1522,14 @@ const useDeepMemo = (value) => {
1549
1522
  if (!(0, import_fast_deep_equal.default)(ref.current, value)) ref.current = value;
1550
1523
  return ref.current;
1551
1524
  };
1552
- //#endregion
1553
- //#region src/providers/chart-scope/use-chart-scope-element.ts
1525
+ // src/providers/chart-scope/use-chart-scope-element.ts
1554
1526
  /**
1555
1527
  * Returns the nearest chart scope element, or `null` when rendered outside any scope (and during SSR, before the ref is attached).
1556
1528
  *
1557
1529
  * @return {HTMLElement | null} The nearest chart scope element, or `null`.
1558
1530
  */
1559
1531
  const useChartScopeElement = () => useContext(ChartScopeContext);
1560
- //#endregion
1561
- //#region src/providers/chart-scope/use-standalone-scope-class.ts
1532
+ // src/providers/chart-scope/use-standalone-scope-class.ts
1562
1533
  /**
1563
1534
  * Returns the catalog class when there is no `GlobalChartsProvider` above this component, and `undefined` when there is.
1564
1535
  *
@@ -1567,8 +1538,7 @@ const useChartScopeElement = () => useContext(ChartScopeContext);
1567
1538
  * @return The scope class name, or undefined when a provider is present.
1568
1539
  */
1569
1540
  const useStandaloneScopeClass = () => useContext(GlobalChartsContext) ? void 0 : CHART_SCOPE_CLASS;
1570
- //#endregion
1571
- //#region src/hooks/use-xychart-theme.ts
1541
+ // src/hooks/use-xychart-theme.ts
1572
1542
  const STARTS_LIKE_A_NUMBER = /^[+-]?[\d.]/;
1573
1543
  const NON_NEGATIVE_CSS_NUMBER = /^\+?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?:[a-z]+|%)?$/i;
1574
1544
  const isRenderableFontSize = (fontSize) => {
@@ -1624,8 +1594,7 @@ const useXYChartTheme = (data) => {
1624
1594
  scopeElement
1625
1595
  ]);
1626
1596
  };
1627
- //#endregion
1628
- //#region src/providers/chart-context/hooks/use-chart-formatting.ts
1597
+ // src/providers/chart-context/hooks/use-chart-formatting.ts
1629
1598
  const RUNTIME_FORMATTING = {};
1630
1599
  /**
1631
1600
  * The locale and time zone dates are rendered in, as set on `GlobalChartsProvider`.
@@ -1639,8 +1608,7 @@ const RUNTIME_FORMATTING = {};
1639
1608
  const useChartFormatting = () => {
1640
1609
  return useContext(GlobalChartsContext)?.formatting ?? RUNTIME_FORMATTING;
1641
1610
  };
1642
- //#endregion
1643
- //#region src/hooks/use-chart-data-transform.ts
1611
+ // src/hooks/use-chart-data-transform.ts
1644
1612
  /**
1645
1613
  * Hook that transforms and sorts chart data, handling date parsing and sorting
1646
1614
  *
@@ -1675,8 +1643,7 @@ const useChartDataTransform = (data) => {
1675
1643
  }));
1676
1644
  }, [data, timeZone]);
1677
1645
  };
1678
- //#endregion
1679
- //#region src/hooks/use-chart-margin.tsx
1646
+ // src/hooks/use-chart-margin.tsx
1680
1647
  /**
1681
1648
  * Base top margin used when no dynamic adjustments are necessary.
1682
1649
  */
@@ -1798,8 +1765,7 @@ const useChartMargin = (height, options, data, theme, horizontal = false) => {
1798
1765
  yTicks
1799
1766
  ]);
1800
1767
  };
1801
- //#endregion
1802
- //#region src/hooks/use-element-size.ts
1768
+ // src/hooks/use-element-size.ts
1803
1769
  /**
1804
1770
  * Hook to measure the width and height of a DOM element.
1805
1771
  * Returns a ref callback to attach to the element and the current dimensions in pixels.
@@ -1836,8 +1802,7 @@ function useElementSize({ initialWidth = 0, initialHeight = 0 } = {}) {
1836
1802
  height
1837
1803
  ];
1838
1804
  }
1839
- //#endregion
1840
- //#region src/hooks/use-text-truncation.ts
1805
+ // src/hooks/use-text-truncation.ts
1841
1806
  /**
1842
1807
  * Hook to detect if text content is truncated within its container.
1843
1808
  * Uses ResizeObserver to dynamically track changes in element size.
@@ -1878,8 +1843,7 @@ function useTextTruncation(enabled = true) {
1878
1843
  } else setIsTruncated(false);
1879
1844
  }, [enabled]), isTruncated];
1880
1845
  }
1881
- //#endregion
1882
- //#region src/hooks/use-zero-value-display.ts
1846
+ // src/hooks/use-zero-value-display.ts
1883
1847
  /**
1884
1848
  * Minimum pixel size for near-zero bars (non-zero values that would render too small).
1885
1849
  * Using 3px to be visible but not misleading - larger values might look like actual data.
@@ -1919,8 +1883,7 @@ const useZeroValueDisplay = (data, options = { enabled: false }) => {
1919
1883
  valueAxisLength
1920
1884
  ]);
1921
1885
  };
1922
- //#endregion
1923
- //#region src/hooks/use-data-with-percentages.ts
1886
+ // src/hooks/use-data-with-percentages.ts
1924
1887
  /**
1925
1888
  * Hook to calculate percentages from values for chart data.
1926
1889
  * Ensures percentages are always derived from values (single source of truth).
@@ -1937,8 +1900,7 @@ const useDataWithPercentages = (data) => {
1937
1900
  }));
1938
1901
  }, [data]);
1939
1902
  };
1940
- //#endregion
1941
- //#region src/hooks/use-legend-visibility-data.ts
1903
+ // src/hooks/use-legend-visibility-data.ts
1942
1904
  /**
1943
1905
  * Custom hook to filter and recalculate chart data based on series visibility.
1944
1906
  *
@@ -2010,8 +1972,7 @@ const useLegendVisibilityData = ({ data, chartId, isSeriesVisible }) => {
2010
1972
  ])
2011
1973
  };
2012
1974
  };
2013
- //#endregion
2014
- //#region src/hooks/use-prefers-reduced-motion.ts
1975
+ // src/hooks/use-prefers-reduced-motion.ts
2015
1976
  const QUERY = "(prefers-reduced-motion: no-preference)";
2016
1977
  const getInitialState = () => !window.matchMedia(QUERY).matches;
2017
1978
  /**
@@ -2032,11 +1993,9 @@ function usePrefersReducedMotion() {
2032
1993
  }, []);
2033
1994
  return prefersReducedMotion;
2034
1995
  }
2035
- //#endregion
2036
- //#region src/hooks/use-isomorphic-layout-effect.ts
1996
+ // src/hooks/use-isomorphic-layout-effect.ts
2037
1997
  const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
2038
- //#endregion
2039
- //#region src/providers/chart-context/hooks/use-chart-registration.ts
1998
+ // src/providers/chart-context/hooks/use-chart-registration.ts
2040
1999
  const useChartRegistration = ({ chartId, legendItems, chartType, isDataValid, metadata }) => {
2041
2000
  const { registerChart, unregisterChart } = useGlobalChartsContext();
2042
2001
  const stableLegendItems = useDeepMemo(legendItems);
@@ -2058,8 +2017,7 @@ const useChartRegistration = ({ chartId, legendItems, chartType, isDataValid, me
2058
2017
  isDataValid
2059
2018
  ]);
2060
2019
  };
2061
- //#endregion
2062
- //#region src/providers/chart-context/hooks/use-global-charts-theme.ts
2020
+ // src/providers/chart-context/hooks/use-global-charts-theme.ts
2063
2021
  /**
2064
2022
  * Hook to get the global chart theme from GlobalChartsProvider
2065
2023
  *
@@ -2068,8 +2026,7 @@ const useChartRegistration = ({ chartId, legendItems, chartType, isDataValid, me
2068
2026
  const useGlobalChartsTheme = () => {
2069
2027
  return useContext(GlobalChartsContext)?.theme ?? defaultTheme;
2070
2028
  };
2071
- //#endregion
2072
- //#region src/components/legend/utils/value-or-identity.ts
2029
+ // src/components/legend/utils/value-or-identity.ts
2073
2030
  /**
2074
2031
  * Returns an object's value if defined, or the object.
2075
2032
  * @param _ - The object to return the value of.
@@ -2087,8 +2044,7 @@ function valueOrIdentity(_) {
2087
2044
  function valueOrIdentityString(_) {
2088
2045
  return String(valueOrIdentity(_));
2089
2046
  }
2090
- //#endregion
2091
- //#region src/components/legend/private/base-legend.module.scss
2047
+ // src/components/legend/private/base-legend.module.scss
2092
2048
  var base_legend_module_default = {
2093
2049
  "legend": "a8ccharts-04TogW-legend",
2094
2050
  "legend--horizontal": "a8ccharts-04TogW-legend--horizontal",
@@ -2100,8 +2056,7 @@ var base_legend_module_default = {
2100
2056
  "legend-item-text--wrap": "a8ccharts-04TogW-legend-item-text--wrap",
2101
2057
  "legend-item-value": "a8ccharts-04TogW-legend-item-value"
2102
2058
  };
2103
- //#endregion
2104
- //#region src/components/legend/private/base-legend.tsx
2059
+ // src/components/legend/private/base-legend.tsx
2105
2060
  const ALIGNMENT_TO_FLEX = {
2106
2061
  start: "flex-start",
2107
2062
  center: "center",
@@ -2266,8 +2221,7 @@ const BaseLegend = forwardRef(({ items: allItems, className, orientation = "hori
2266
2221
  })
2267
2222
  });
2268
2223
  });
2269
- //#endregion
2270
- //#region src/components/legend/legend.tsx
2224
+ // src/components/legend/legend.tsx
2271
2225
  const defaultShapeByChartType = {
2272
2226
  area: "rect",
2273
2227
  line: "line",
@@ -2293,8 +2247,7 @@ const Legend = forwardRef(({ chartId, items, shape, ...props }, ref) => {
2293
2247
  chartId: contextChartId
2294
2248
  });
2295
2249
  });
2296
- //#endregion
2297
- //#region src/components/legend/hooks/use-chart-legend-items.ts
2250
+ // src/components/legend/hooks/use-chart-legend-items.ts
2298
2251
  /**
2299
2252
  * Wraps `getElementStyles` so a swatch takes the color given for its series.
2300
2253
  * @param getElementStyles - Function to get element styles
@@ -2550,15 +2503,13 @@ function useChartLegendItems(data, options = {}, legendShape) {
2550
2503
  legendShape
2551
2504
  ]);
2552
2505
  }
2553
- //#endregion
2554
- //#region src/components/tooltip/private/label-value-content.tsx
2506
+ // src/components/tooltip/private/label-value-content.tsx
2555
2507
  const LabelValueContent = ({ data }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
2556
2508
  data.label,
2557
2509
  ": ",
2558
2510
  data.valueDisplay || formatNumber(data.value)
2559
2511
  ] });
2560
- //#endregion
2561
- //#region src/components/tooltip/private/tooltip-theme.tsx
2512
+ // src/components/tooltip/private/tooltip-theme.tsx
2562
2513
  const DEFAULT_SURFACE = "#1e1e1e";
2563
2514
  const TOOLTIP_SURFACE = `var(--a8c-charts-color-tooltip-surface, ${DEFAULT_SURFACE})`;
2564
2515
  const toSeed = (value) => {
@@ -2581,11 +2532,9 @@ const TooltipTheme = ({ children }) => {
2581
2532
  children
2582
2533
  });
2583
2534
  };
2584
- //#endregion
2585
- //#region src/components/tooltip/tooltip-box.module.scss
2535
+ // src/components/tooltip/tooltip-box.module.scss
2586
2536
  var tooltip_box_module_default = { "surface": "a8ccharts-ddpU1W-surface" };
2587
- //#endregion
2588
- //#region src/components/tooltip/tooltip-box.tsx
2537
+ // src/components/tooltip/tooltip-box.tsx
2589
2538
  /**
2590
2539
  * The chart tooltip box: the dark surface every chart tooltip draws. It does not position itself; place it with `style` or a wrapper.
2591
2540
  *
@@ -2605,8 +2554,7 @@ const TooltipBox = forwardRef(({ unstyled = false, role = "tooltip", className,
2605
2554
  return unstyled ? box : /* @__PURE__ */ jsx(TooltipTheme, { children: box });
2606
2555
  });
2607
2556
  TooltipBox.displayName = "TooltipBox";
2608
- //#endregion
2609
- //#region src/components/tooltip/base-tooltip.tsx
2557
+ // src/components/tooltip/base-tooltip.tsx
2610
2558
  /**
2611
2559
  * A tooltip box with children or `label: value` content. Prefer `TooltipBox`.
2612
2560
  *
@@ -2640,6 +2588,80 @@ const BaseTooltip = ({ data, top, left, component: Component = LabelValueContent
2640
2588
  children: content
2641
2589
  });
2642
2590
  };
2591
+ // src/components/tooltip/private/keyboard-stops.ts
2592
+ const timeOf$1 = (point) => point?.date?.getTime();
2593
+ const getXPositions = (series) => {
2594
+ const positions = /* @__PURE__ */ new Set();
2595
+ for (const { data } of series) for (const point of data) {
2596
+ const time = timeOf$1(point);
2597
+ if (time !== void 0) positions.add(time);
2598
+ }
2599
+ return [...positions].sort((a, b) => a - b);
2600
+ };
2601
+ /**
2602
+ * Keyboard stops over the series: the sorted union of their dates, or array indexes when no point has a date.
2603
+ *
2604
+ * Once any point has a date, a series of undated points has no stop.
2605
+ *
2606
+ * @param series - The series to step through.
2607
+ * @return The stop count, and each series' point at a stop.
2608
+ */
2609
+ const getKeyboardStops = (series) => {
2610
+ const positions = getXPositions(series);
2611
+ if (positions.length === 0) return {
2612
+ count: Math.max(0, ...series.map(({ data }) => data.length)),
2613
+ membersAt: (stop) => series.flatMap((s) => stop < s.data.length ? [{
2614
+ series: s,
2615
+ datum: s.data[stop],
2616
+ index: stop
2617
+ }] : [])
2618
+ };
2619
+ return {
2620
+ count: positions.length,
2621
+ membersAt: (stop) => {
2622
+ const time = positions[stop];
2623
+ if (time === void 0) return [];
2624
+ return series.flatMap((s) => {
2625
+ const index = s.data.findIndex((point) => timeOf$1(point) === time);
2626
+ return index === -1 ? [] : [{
2627
+ series: s,
2628
+ datum: s.data[index],
2629
+ index
2630
+ }];
2631
+ });
2632
+ }
2633
+ };
2634
+ };
2635
+ // src/components/tooltip/private/at-nearest-date.ts
2636
+ const timeOf = (datum) => datum.date?.getTime();
2637
+ /**
2638
+ * Lists every registered series at the nearest datum's date, each with its own point there.
2639
+ *
2640
+ * The pointer hands each series its own nearest point, which for a series that skips that date, or that the pointer sits nearer another date of, is a neighbor's.
2641
+ *
2642
+ * @param tooltipData - The tooltip data visx collected.
2643
+ * @param registry - The chart's data registry.
2644
+ * @return The tooltip data, unchanged when the nearest datum has no date.
2645
+ */
2646
+ const atNearestDate = (tooltipData, registry) => {
2647
+ const nearest = tooltipData?.nearestDatum?.datum;
2648
+ const time = nearest ? timeOf(nearest) : void 0;
2649
+ if (!tooltipData || time === void 0) return tooltipData;
2650
+ const datumByKey = {};
2651
+ for (const { key, data } of registry?.entries() ?? []) {
2652
+ const index = data.findIndex((datum) => timeOf(datum) === time);
2653
+ if (index !== -1) datumByKey[key] = {
2654
+ key,
2655
+ index,
2656
+ datum: data[index]
2657
+ };
2658
+ }
2659
+ for (const [key, entry] of Object.entries(tooltipData.datumByKey)) if (!datumByKey[key] && timeOf(entry.datum) === time) datumByKey[key] = entry;
2660
+ return {
2661
+ ...tooltipData,
2662
+ datumByKey
2663
+ };
2664
+ };
2643
2665
  const POINTER_HEIGHT = 6;
2644
2666
  const clamp = (position, min, max, size) => Math.min(Math.max(position, min), Math.max(min, max - size));
2645
2667
  const isClipping = (element) => {
@@ -2818,8 +2840,7 @@ const BoundedTooltip = ({ left = 0, top = 0, offsetLeft = 10, offsetTop = 10, st
2818
2840
  }), children]
2819
2841
  });
2820
2842
  };
2821
- //#endregion
2822
- //#region src/components/tooltip/private/xy-chart-tooltip-overlay.tsx
2843
+ // src/components/tooltip/private/xy-chart-tooltip-overlay.tsx
2823
2844
  const CROSSHAIR_STROKE_WIDTH = 1.5;
2824
2845
  const CROSSHAIR_PAINT_PROPERTIES = /* @__PURE__ */ new Set([
2825
2846
  "stroke",
@@ -3004,18 +3025,21 @@ const XyChartTooltipContent = ({ tooltipContext, container, renderTooltip, rende
3004
3025
  */
3005
3026
  const XyChartTooltipOverlay = (props) => {
3006
3027
  const tooltipContext = useContext(TooltipContext);
3028
+ const dataRegistry = useContext(DataContext)?.dataRegistry;
3007
3029
  const [container, setContainer] = useState(null);
3008
3030
  const anchorRef = useCallback((node) => {
3009
3031
  setContainer(node?.ownerSVGElement?.parentElement ?? null);
3010
3032
  }, []);
3011
3033
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("g", { ref: anchorRef }), tooltipContext?.tooltipOpen && /* @__PURE__ */ jsx(XyChartTooltipContent, {
3012
3034
  ...props,
3013
- tooltipContext,
3035
+ tooltipContext: {
3036
+ ...tooltipContext,
3037
+ tooltipData: atNearestDate(tooltipContext.tooltipData, dataRegistry)
3038
+ },
3014
3039
  container
3015
3040
  })] });
3016
3041
  };
3017
- //#endregion
3018
- //#region src/components/tooltip/xy-chart-tooltip.tsx
3042
+ // src/components/tooltip/xy-chart-tooltip.tsx
3019
3043
  const XYChartTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocusedClassName, series = [], mode = "group", verticalCrosshairStyle, horizontalCrosshairStyle, ...props }) => {
3020
3044
  const tooltipContext = useContext(TooltipContext);
3021
3045
  const scopeElement = useChartScopeElement();
@@ -3040,6 +3064,7 @@ const XYChartTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocu
3040
3064
  }
3041
3065
  return flattened;
3042
3066
  }, [series, mode]);
3067
+ const stops = useMemo(() => getKeyboardStops(series), [series]);
3043
3068
  const hasKeyboardSelection = useRef(false);
3044
3069
  const closeTooltipNow = useCallback(() => {
3045
3070
  tooltipContext?.updateTooltip({
@@ -3073,19 +3098,20 @@ const XYChartTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocu
3073
3098
  hasKeyboardSelection.current = true;
3074
3099
  if (mode === "group") {
3075
3100
  closeTooltipNow();
3076
- series.forEach((s, index) => {
3077
- if (selectedIndex < s.data.length) {
3078
- const datum = s.data[selectedIndex];
3079
- tooltipContext?.showTooltip({
3080
- datum,
3081
- key: s.label,
3082
- index
3083
- });
3084
- }
3101
+ stops.membersAt(selectedIndex).forEach(({ series: member, datum, index }) => {
3102
+ tooltipContext?.showTooltip({
3103
+ datum,
3104
+ key: member.label,
3105
+ index
3106
+ });
3085
3107
  });
3086
3108
  } else if (mode === "individual") {
3087
3109
  if (selectedIndex < tooltipData.length) {
3088
3110
  const tooltipItem = tooltipData[selectedIndex];
3111
+ tooltipContext?.updateTooltip((state) => ({
3112
+ ...state,
3113
+ tooltipData: void 0
3114
+ }));
3089
3115
  tooltipContext?.showTooltip({
3090
3116
  datum: tooltipItem.datum,
3091
3117
  key: tooltipItem.seriesLabel,
@@ -3096,7 +3122,7 @@ const XYChartTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardFocu
3096
3122
  }, [
3097
3123
  selectedIndex,
3098
3124
  tooltipData,
3099
- series
3125
+ stops
3100
3126
  ]);
3101
3127
  const focusableRenderTooltip = useMemo(() => {
3102
3128
  if (!renderTooltip) return void 0;
@@ -3246,8 +3272,7 @@ const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating,
3246
3272
  onChartPointerMove
3247
3273
  };
3248
3274
  };
3249
- //#endregion
3250
- //#region src/providers/chart-context/hooks/use-default-hidden-series.ts
3275
+ // src/providers/chart-context/hooks/use-default-hidden-series.ts
3251
3276
  /**
3252
3277
  * Seeds a chart's hidden series once per chart ID, the first time the provider
3253
3278
  * sees that ID.
@@ -3282,8 +3307,7 @@ const useDefaultHiddenSeries = (chartId, seriesLabels) => {
3282
3307
  chartId
3283
3308
  ]);
3284
3309
  };
3285
- //#endregion
3286
- //#region src/charts/private/chart-composition/chart-svg.tsx
3310
+ // src/charts/private/chart-composition/chart-svg.tsx
3287
3311
  /**
3288
3312
  * Compound component for SVG children in charts.
3289
3313
  * This component serves as a marker for SVG content that should be rendered
@@ -3297,8 +3321,7 @@ const ChartSVG = ({ children }) => {
3297
3321
  return /* @__PURE__ */ jsx(Fragment$1, { children });
3298
3322
  };
3299
3323
  ChartSVG.displayName = "Chart.SVG";
3300
- //#endregion
3301
- //#region src/charts/private/chart-composition/chart-html.tsx
3324
+ // src/charts/private/chart-composition/chart-html.tsx
3302
3325
  /**
3303
3326
  * Compound component for HTML children in charts.
3304
3327
  * This component serves as a marker for HTML content that should be rendered
@@ -3312,8 +3335,7 @@ const ChartHTML = ({ children }) => {
3312
3335
  return /* @__PURE__ */ jsx(Fragment$1, { children });
3313
3336
  };
3314
3337
  ChartHTML.displayName = "Chart.HTML";
3315
- //#endregion
3316
- //#region src/charts/private/chart-composition/render-legend-slot.ts
3338
+ // src/charts/private/chart-composition/render-legend-slot.ts
3317
3339
  /**
3318
3340
  * Renders legend children filtered by position slot.
3319
3341
  *
@@ -3324,8 +3346,7 @@ ChartHTML.displayName = "Chart.HTML";
3324
3346
  function renderLegendSlot(legendChildren, position) {
3325
3347
  return legendChildren.filter((l) => l.position === position).map((l, i) => createElement(Fragment, { key: `legend-${position}-${i}` }, l.element));
3326
3348
  }
3327
- //#endregion
3328
- //#region src/charts/private/chart-composition/use-chart-children.ts
3349
+ // src/charts/private/chart-composition/use-chart-children.ts
3329
3350
  /**
3330
3351
  * Custom hook to process and categorize chart children for composition API.
3331
3352
  * Extracts children from compound components (Chart.SVG, Chart.HTML) and
@@ -3378,11 +3399,9 @@ function useChartChildren(children, chartType) {
3378
3399
  };
3379
3400
  }, [children, chartType]);
3380
3401
  }
3381
- //#endregion
3382
- //#region src/charts/private/chart-layout/chart-layout.module.scss
3402
+ // src/charts/private/chart-layout/chart-layout.module.scss
3383
3403
  var chart_layout_module_default = { "chart-layout__content": "a8ccharts-fpNVAq-chart-layout__content" };
3384
- //#endregion
3385
- //#region src/charts/private/chart-layout/chart-layout.tsx
3404
+ // src/charts/private/chart-layout/chart-layout.tsx
3386
3405
  const ChartLayout = ({ legendPosition, legendElement, legendChildren, children, trailingContent, onContentHeightChange, gap, className, rootRef, style, "data-testid": dataTestId, "data-chart-id": dataChartId }) => {
3387
3406
  const [contentRef, contentWidth, contentHeight] = useElementSize();
3388
3407
  const isRenderProp = typeof children === "function";
@@ -3425,8 +3444,7 @@ const ChartLayout = ({ legendPosition, legendElement, legendChildren, children,
3425
3444
  ]
3426
3445
  });
3427
3446
  };
3428
- //#endregion
3429
- //#region src/charts/private/default-glyph/default-glyph.tsx
3447
+ // src/charts/private/default-glyph/default-glyph.tsx
3430
3448
  const DefaultGlyph = (props) => {
3431
3449
  const { theme } = useContext(DataContext) || {};
3432
3450
  props.position;
@@ -3441,8 +3459,7 @@ const DefaultGlyph = (props) => {
3441
3459
  ...props.glyphStyle
3442
3460
  });
3443
3461
  };
3444
- //#endregion
3445
- //#region src/charts/private/readings.ts
3462
+ // src/charts/private/readings.ts
3446
3463
  /**
3447
3464
  * Whether a value is a reading a scale can place.
3448
3465
  *
@@ -3466,11 +3483,9 @@ const isInvalidReading = (value, { allowMissing }) => value === null ? !allowMis
3466
3483
  * @return The formatted value.
3467
3484
  */
3468
3485
  const formatReading = (value) => value == null ? __("No data", "jetpack-charts") : formatNumber(value);
3469
- //#endregion
3470
- //#region src/charts/private/center/center.module.scss
3486
+ // src/charts/private/center/center.module.scss
3471
3487
  var center_module_default = { "center": "a8ccharts-w3qxlG-center" };
3472
- //#endregion
3473
- //#region src/charts/private/center/center.tsx
3488
+ // src/charts/private/center/center.tsx
3474
3489
  /**
3475
3490
  * Centers its children on both axes and fills its parent.
3476
3491
  *
@@ -3492,11 +3507,9 @@ const Center = forwardRef(({ align = "center", justify = "center", className, ..
3492
3507
  ...props
3493
3508
  }));
3494
3509
  Center.displayName = "Center";
3495
- //#endregion
3496
- //#region src/charts/private/svg-empty-state/svg-empty-state.module.scss
3510
+ // src/charts/private/svg-empty-state/svg-empty-state.module.scss
3497
3511
  var svg_empty_state_module_default = { "svg-empty-state": "a8ccharts-udGPVq-svg-empty-state" };
3498
- //#endregion
3499
- //#region src/charts/private/svg-empty-state/svg-empty-state.tsx
3512
+ // src/charts/private/svg-empty-state/svg-empty-state.tsx
3500
3513
  /**
3501
3514
  * Renders empty-state text inside an SVG using foreignObject so that the
3502
3515
  * message wraps onto multiple lines instead of being clipped.
@@ -3523,8 +3536,7 @@ const SvgEmptyState = ({ x, y, width, height, children }) => {
3523
3536
  })
3524
3537
  });
3525
3538
  };
3526
- //#endregion
3527
- //#region src/charts/private/svg-empty-state/get-all-hidden-message.ts
3539
+ // src/charts/private/svg-empty-state/get-all-hidden-message.ts
3528
3540
  /**
3529
3541
  * Return the empty-state message for a chart whose items are all hidden.
3530
3542
  *
@@ -3544,8 +3556,7 @@ const getAllHiddenMessage = (interactive, itemType) => {
3544
3556
  if (interactive) return _x("All series are hidden. Click legend items to show data.", "chart empty state: interactive series", "jetpack-charts");
3545
3557
  return _x("All series are hidden.", "chart empty state: series", "jetpack-charts");
3546
3558
  };
3547
- //#endregion
3548
- //#region src/charts/private/time-axis.ts
3559
+ // src/charts/private/time-axis.ts
3549
3560
  const X_TICK_WIDTH = 60;
3550
3561
  const getCurveType = (type, smoothing) => {
3551
3562
  if (!type) return smoothing ? curveCatmullRom : curveLinear;
@@ -3802,8 +3813,7 @@ const guessOptimalNumTicks = (data, chartWidth, tickFormatter) => {
3802
3813
  }
3803
3814
  return Math.max(1, secondBestGuess);
3804
3815
  };
3805
- //#endregion
3806
- //#region src/charts/private/time-axis-options.ts
3816
+ // src/charts/private/time-axis-options.ts
3807
3817
  const toDateDomain = (domain) => domain ? [new Date(domain[0]), new Date(domain[1])] : void 0;
3808
3818
  /**
3809
3819
  * The x-axis options for a continuous time chart, shared by LineChart and AreaChart.
@@ -3838,8 +3848,7 @@ const buildTimeAxisOptions = ({ dataSorted, width, axisOptions, scaleDomain, zoo
3838
3848
  ...numTicks === void 0 ? {} : { numTicks }
3839
3849
  };
3840
3850
  };
3841
- //#endregion
3842
- //#region src/charts/private/whole-number-ticks.tsx
3851
+ // src/charts/private/whole-number-ticks.tsx
3843
3852
  /**
3844
3853
  * Whether every reading in the series is a whole number.
3845
3854
  *
@@ -3886,15 +3895,13 @@ const WholeNumberTicks = ({ axis, numTicks, enabled, children }) => {
3886
3895
  const tickValues = enabled ? getWholeNumberTickValues(axis === "x" ? xScale : yScale, numTicks) : void 0;
3887
3896
  return /* @__PURE__ */ jsx(Fragment$1, { children: children(tickValues) });
3888
3897
  };
3889
- //#endregion
3890
- //#region src/charts/private/with-responsive/with-responsive.module.scss
3898
+ // src/charts/private/with-responsive/with-responsive.module.scss
3891
3899
  var with_responsive_module_default = {
3892
3900
  "container": "a8ccharts-sP1gHa-container",
3893
3901
  "content": "a8ccharts-sP1gHa-content",
3894
3902
  "isContained": "a8ccharts-sP1gHa-isContained"
3895
3903
  };
3896
- //#endregion
3897
- //#region src/charts/private/with-responsive/with-responsive.tsx
3904
+ // src/charts/private/with-responsive/with-responsive.tsx
3898
3905
  /**
3899
3906
  * A higher-order component that provides responsive dimensions
3900
3907
  * to the wrapped chart component using useParentSize from `@visx/responsive`.
@@ -3973,14 +3980,12 @@ function withResponsive(WrappedComponent) {
3973
3980
  });
3974
3981
  };
3975
3982
  }
3976
- //#endregion
3977
- //#region src/charts/private/x-zoom/x-zoom.module.scss
3983
+ // src/charts/private/x-zoom/x-zoom.module.scss
3978
3984
  var x_zoom_module_default = {
3979
3985
  "x-zoom__reset": "a8ccharts-ur9dWW-x-zoom__reset",
3980
3986
  "x-zoom__selection": "a8ccharts-ur9dWW-x-zoom__selection"
3981
3987
  };
3982
- //#endregion
3983
- //#region src/charts/private/x-zoom/x-zoom.tsx
3988
+ // src/charts/private/x-zoom/x-zoom.tsx
3984
3989
  const MIN_DRAG_PIXELS = 6;
3985
3990
  /**
3986
3991
  * Drag-to-zoom state + pointer handlers for an XY chart. Designed to be
@@ -4163,11 +4168,9 @@ function ZoomResetButton({ onClick }) {
4163
4168
  })
4164
4169
  });
4165
4170
  }
4166
- //#endregion
4167
- //#region src/charts/private/xy-plot/xy-plot.module.scss
4171
+ // src/charts/private/xy-plot/xy-plot.module.scss
4168
4172
  var xy_plot_module_default = { "xy-plot": "a8ccharts-bIyhgG-xy-plot" };
4169
- //#endregion
4170
- //#region src/charts/line-chart/line-chart.module.scss
4173
+ // src/charts/line-chart/line-chart.module.scss
4171
4174
  var line_chart_module_default = {
4172
4175
  "line-chart": "a8ccharts-inuQka-line-chart",
4173
4176
  "line-chart__annotation-label": "a8ccharts-inuQka-line-chart__annotation-label",
@@ -4269,8 +4272,7 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
4269
4272
  })]
4270
4273
  });
4271
4274
  };
4272
- //#endregion
4273
- //#region src/charts/line-chart/private/line-chart-annotations-overlay.tsx
4275
+ // src/charts/line-chart/private/line-chart-annotations-overlay.tsx
4274
4276
  const LineChartAnnotationsOverlay = ({ children }) => {
4275
4277
  const { chartRef, chartWidth, chartHeight } = useChartInstanceContext();
4276
4278
  const [scales, setScales] = useState(null);
@@ -4353,8 +4355,7 @@ const LineChartAnnotationsOverlay = ({ children }) => {
4353
4355
  })
4354
4356
  });
4355
4357
  };
4356
- //#endregion
4357
- //#region src/charts/line-chart/private/line-chart-annotation.tsx
4358
+ // src/charts/line-chart/private/line-chart-annotation.tsx
4358
4359
  const ANNOTATION_MAX_WIDTH = 125;
4359
4360
  const ANNOTATION_INIT_HEIGHT = 100;
4360
4361
  const getLabelPosition = ({ subjectType, x, xMax, y, yMin, yMax, maxWidth, height }) => {
@@ -4547,8 +4548,7 @@ const LineChartAnnotation = ({ datum, title, subtitle, subjectType = "circle", s
4547
4548
  ]
4548
4549
  }) });
4549
4550
  };
4550
- //#endregion
4551
- //#region src/charts/line-chart/private/line-chart-glyph.tsx
4551
+ // src/charts/line-chart/private/line-chart-glyph.tsx
4552
4552
  const toNumber$1 = (val) => {
4553
4553
  const num = typeof val === "number" ? val : parseFloat(val);
4554
4554
  return isNaN(num) ? void 0 : num;
@@ -4578,8 +4578,7 @@ const LineChartGlyph = ({ data, index, color, glyphStyle, renderGlyph, accessors
4578
4578
  position
4579
4579
  });
4580
4580
  };
4581
- //#endregion
4582
- //#region src/charts/line-chart/private/nearest-pointer-events.tsx
4581
+ // src/charts/line-chart/private/nearest-pointer-events.tsx
4583
4582
  /**
4584
4583
  * Find the datum nearest a pointer along x, in one series sorted by x.
4585
4584
  *
@@ -4678,8 +4677,7 @@ function NearestPointerEvents({ onPointerDown, onPointerMove, onPointerUp }) {
4678
4677
  useEventEmitter("pointerup", handlers.pointerup);
4679
4678
  return null;
4680
4679
  }
4681
- //#endregion
4682
- //#region src/charts/line-chart/line-chart.tsx
4680
+ // src/charts/line-chart/line-chart.tsx
4683
4681
  const defaultRenderGlyph = (props) => {
4684
4682
  return /* @__PURE__ */ createElement(DefaultGlyph, {
4685
4683
  ...props,
@@ -4861,21 +4859,22 @@ const LineChartInternal = forwardRef(({ data, ariaLabel, chartId: providedChartI
4861
4859
  isSeriesVisible,
4862
4860
  options?.yScale
4863
4861
  ]);
4864
- const activateSelectedPoint = useCallback((index) => {
4865
- const series = visibleSeries.find((candidate) => candidate.data[index]);
4866
- if (series) onDatumActivate?.({
4867
- datum: series.data[index],
4868
- index,
4869
- key: series.label
4862
+ const stops = useMemo(() => getKeyboardStops(visibleSeries), [visibleSeries]);
4863
+ const activateSelectedPoint = useCallback((stop) => {
4864
+ const match = stops.membersAt(stop)[0];
4865
+ if (match) onDatumActivate?.({
4866
+ datum: match.datum,
4867
+ index: match.index,
4868
+ key: match.series.label
4870
4869
  });
4871
- }, [visibleSeries, onDatumActivate]);
4870
+ }, [stops, onDatumActivate]);
4872
4871
  const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
4873
4872
  selectedIndex,
4874
4873
  setSelectedIndex,
4875
4874
  isNavigating,
4876
4875
  setIsNavigating,
4877
4876
  chartRef,
4878
- totalPoints: Math.max(0, ...visibleSeries.map((series) => series.data.length)),
4877
+ totalPoints: stops.count,
4879
4878
  visibleSeriesKey,
4880
4879
  onActivate: activateSelectedPoint,
4881
4880
  preventTooltipScroll: tooltipPlacement === "below-axis"
@@ -5209,15 +5208,13 @@ const LineChartResponsive = attachSubComponents(withResponsive(LineChartWithProv
5209
5208
  AnnotationsOverlay: LineChartAnnotationsOverlay,
5210
5209
  Annotation: LineChartAnnotation
5211
5210
  });
5212
- //#endregion
5213
- //#region src/charts/area-chart/area-chart.module.scss
5211
+ // src/charts/area-chart/area-chart.module.scss
5214
5212
  var area_chart_module_default = {
5215
5213
  "area-chart": "a8ccharts-jlynaq-area-chart",
5216
5214
  "area-chart--animated": "a8ccharts-jlynaq-area-chart--animated",
5217
5215
  "rise": "a8ccharts-jlynaq-rise"
5218
5216
  };
5219
- //#endregion
5220
- //#region src/charts/area-chart/private/validate-data.ts
5217
+ // src/charts/area-chart/private/validate-data.ts
5221
5218
  /**
5222
5219
  * Up-front data validation. Returns a localised error message when the chart
5223
5220
  * cannot safely render, otherwise `null`. Catches the cases that would
@@ -5233,8 +5230,7 @@ const validateData$3 = (data) => {
5233
5230
  if (data.some((series) => series.data.some((point) => isInvalidReading(point.value, { allowMissing: false }) || "date" in point && point.date && isNaN(point.date.getTime())))) return __("Invalid data", "jetpack-charts");
5234
5231
  return null;
5235
5232
  };
5236
- //#endregion
5237
- //#region src/charts/area-chart/private/overlays.tsx
5233
+ // src/charts/area-chart/private/overlays.tsx
5238
5234
  const AreaChartScalesRef = ({ chartRef, width, height, margin }) => {
5239
5235
  const context = useContext(DataContext);
5240
5236
  useImperativeHandle(chartRef, () => ({
@@ -5299,8 +5295,7 @@ const HoverGlyphs = ({ visibleSeries, stacked, stackOffset, getElementStyles, st
5299
5295
  children: circles
5300
5296
  });
5301
5297
  };
5302
- //#endregion
5303
- //#region src/charts/area-chart/area-chart.tsx
5298
+ // src/charts/area-chart/area-chart.tsx
5304
5299
  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) => {
5305
5300
  const legendInteractive = legend.interactive ?? false;
5306
5301
  const legendShape = legend.shape ?? "rect";
@@ -5346,19 +5341,22 @@ const AreaChartInternal = forwardRef(({ data, ariaLabel, chartId: providedChartI
5346
5341
  }));
5347
5342
  }, [dataSorted, hiddenSeries]);
5348
5343
  const allSeriesHidden = useMemo(() => seriesWithVisibility.every(({ isVisible }) => !isVisible), [seriesWithVisibility]);
5349
- const hasWholeNumberValues = useMemo(() => (!stacked || stackOffset === "none") && hasOnlyWholeNumbers(dataSorted.filter((series) => isSeriesVisible(series.label))), [
5350
- dataSorted,
5351
- isSeriesVisible,
5344
+ const visibleDataSeries = useMemo(() => dataSorted.filter((series) => isSeriesVisible(series.label)), [dataSorted, isSeriesVisible]);
5345
+ const hasWholeNumberValues = useMemo(() => (!stacked || stackOffset === "none") && hasOnlyWholeNumbers(visibleDataSeries), [
5346
+ visibleDataSeries,
5352
5347
  stacked,
5353
5348
  stackOffset
5354
5349
  ]);
5350
+ const visibleSeriesKey = useMemo(() => JSON.stringify(visibleDataSeries.map((series) => series.label)), [visibleDataSeries]);
5351
+ const stops = useMemo(() => getKeyboardStops(visibleDataSeries), [visibleDataSeries]);
5355
5352
  const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
5356
5353
  selectedIndex,
5357
5354
  setSelectedIndex,
5358
5355
  isNavigating,
5359
5356
  setIsNavigating,
5360
5357
  chartRef,
5361
- totalPoints: dataSorted[0]?.data.length || 0
5358
+ totalPoints: stops.count,
5359
+ visibleSeriesKey
5362
5360
  });
5363
5361
  const fixedYDomain = useMemo(() => {
5364
5362
  if (rescaleYOnVisibilityChange || !dataSorted.length || !dataSorted[0].data.length || stacked && stackOffset !== "none") return;
@@ -5646,7 +5644,7 @@ const AreaChartInternal = forwardRef(({ data, ariaLabel, chartId: providedChartI
5646
5644
  selectedIndex,
5647
5645
  tooltipRef,
5648
5646
  keyboardFocusedClassName: area_chart_module_default["area-chart__tooltip--keyboard-focused"],
5649
- series: dataSorted
5647
+ series: visibleDataSeries
5650
5648
  }), /* @__PURE__ */ jsx(HoverGlyphs, {
5651
5649
  visibleSeries,
5652
5650
  stacked,
@@ -5682,8 +5680,7 @@ const AreaChartWithProvider = forwardRef((props, ref) => {
5682
5680
  AreaChartWithProvider.displayName = "AreaChart";
5683
5681
  const AreaChart = attachSubComponents(AreaChartWithProvider, { Legend });
5684
5682
  const AreaChartResponsive = attachSubComponents(withResponsive(AreaChartWithProvider), { Legend });
5685
- //#endregion
5686
- //#region src/charts/bar-chart/bar-chart.module.scss
5683
+ // src/charts/bar-chart/bar-chart.module.scss
5687
5684
  var bar_chart_module_default = {
5688
5685
  "bar-chart": "a8ccharts-97yN9W-bar-chart",
5689
5686
  "bar-chart--animated": "a8ccharts-97yN9W-bar-chart--animated",
@@ -5691,8 +5688,7 @@ var bar_chart_module_default = {
5691
5688
  "rise": "a8ccharts-97yN9W-rise",
5692
5689
  "stretch": "a8ccharts-97yN9W-stretch"
5693
5690
  };
5694
- //#endregion
5695
- //#region src/charts/bar-chart/private/truncated-tick-component.tsx
5691
+ // src/charts/bar-chart/private/truncated-tick-component.tsx
5696
5692
  /**
5697
5693
  * Get the bandwidth of a scale
5698
5694
  *
@@ -5806,8 +5802,7 @@ const createTruncatedTickComponent = (axis) => (props) => {
5806
5802
  */
5807
5803
  const TruncatedXTickComponent = createTruncatedTickComponent("x");
5808
5804
  const TruncatedYTickComponent = createTruncatedTickComponent("y");
5809
- //#endregion
5810
- //#region src/charts/bar-chart/private/value-domain.ts
5805
+ // src/charts/bar-chart/private/value-domain.ts
5811
5806
  /** Domain for a value axis that has nothing to scale, so its ticks still read 0 to 1. */
5812
5807
  const EMPTY_DOMAIN = [0, 1];
5813
5808
  /**
@@ -5858,8 +5853,7 @@ const getValueScaleDomain = (data, includeZero, isSeriesRendered) => {
5858
5853
  if (includeZero) return [Math.min(0, min), Math.max(0, max)];
5859
5854
  return null;
5860
5855
  };
5861
- //#endregion
5862
- //#region src/charts/bar-chart/private/use-bar-chart-options.ts
5856
+ // src/charts/bar-chart/private/use-bar-chart-options.ts
5863
5857
  /** Outer padding of the category band scale (space at the chart edges). */
5864
5858
  const BASE_BAND_PADDING = .2;
5865
5859
  /** Inner padding of the category band scale (the base gap between ticks). */
@@ -6075,8 +6069,7 @@ function useBarChartOptions(data, horizontal, options = {}, isSeriesRendered = A
6075
6069
  isSeriesRendered
6076
6070
  ]);
6077
6071
  }
6078
- //#endregion
6079
- //#region src/charts/bar-chart/private/band-scale.ts
6072
+ // src/charts/bar-chart/private/band-scale.ts
6080
6073
  /**
6081
6074
  * Match the inner slot scale used by visx BarGroup.
6082
6075
  * @param keys - Visible primary series keys.
@@ -6089,8 +6082,7 @@ const createGroupScale = (keys, bandwidth, padding) => scaleBand({
6089
6082
  range: [0, bandwidth],
6090
6083
  padding
6091
6084
  });
6092
- //#endregion
6093
- //#region src/charts/bar-chart/private/comparison-bars-geometry.ts
6085
+ // src/charts/bar-chart/private/comparison-bars-geometry.ts
6094
6086
  /**
6095
6087
  * Mirrors visx's getScaleBaseline so bars drawn outside visx share the baseline of its bars, including out-of-domain zero values.
6096
6088
  *
@@ -6136,8 +6128,7 @@ function computeSlotRect(params) {
6136
6128
  height: valueLength
6137
6129
  };
6138
6130
  }
6139
- //#endregion
6140
- //#region src/charts/bar-chart/private/classified-bar-series.tsx
6131
+ // src/charts/bar-chart/private/classified-bar-series.tsx
6141
6132
  const ClassifiedBarSeries = ({ barClassName, primaryKeys, groupPadding, ...props }) => {
6142
6133
  const { xScale, yScale, horizontal } = useContext(DataContext);
6143
6134
  const bandScale = horizontal ? yScale : xScale;
@@ -6181,8 +6172,7 @@ const ClassifiedBarSeries = ({ barClassName, primaryKeys, groupPadding, ...props
6181
6172
  renderGlyph
6182
6173
  });
6183
6174
  };
6184
- //#endregion
6185
- //#region src/charts/bar-chart/private/slotted-bar-series.tsx
6175
+ // src/charts/bar-chart/private/slotted-bar-series.tsx
6186
6176
  const SlottedBarSeries = ({ barClassName, slotKeys, slotKey, thickness, groupPadding, ...props }) => {
6187
6177
  const { xScale, yScale, horizontal } = useContext(DataContext);
6188
6178
  const bandScale = horizontal ? yScale : xScale;
@@ -6225,16 +6215,14 @@ const SlottedBarSeries = ({ barClassName, slotKeys, slotKey, thickness, groupPad
6225
6215
  renderGlyph
6226
6216
  });
6227
6217
  };
6228
- //#endregion
6229
- //#region src/charts/private/selected-ring/selected-ring.module.scss
6218
+ // src/charts/private/selected-ring/selected-ring.module.scss
6230
6219
  var selected_ring_module_default = {
6231
6220
  "selected-ring__contrast": "a8ccharts-gx1_AW-selected-ring__contrast",
6232
6221
  "selected-ring__edge": "a8ccharts-gx1_AW-selected-ring__edge",
6233
6222
  "selected-ring__far": "a8ccharts-gx1_AW-selected-ring__far",
6234
6223
  "selected-ring__focus": "a8ccharts-gx1_AW-selected-ring__focus"
6235
6224
  };
6236
- //#endregion
6237
- //#region src/charts/private/selected-ring/selected-ring.tsx
6225
+ // src/charts/private/selected-ring/selected-ring.tsx
6238
6226
  const TONES = {
6239
6227
  inside: ["contrast", "focus"],
6240
6228
  outside: ["focus", "contrast"]
@@ -6281,8 +6269,7 @@ const SelectedRing = ({ chartId, d, side, testId }) => {
6281
6269
  ]
6282
6270
  });
6283
6271
  };
6284
- //#endregion
6285
- //#region src/charts/bar-chart/private/selected-bar-ring.tsx
6272
+ // src/charts/bar-chart/private/selected-bar-ring.tsx
6286
6273
  /**
6287
6274
  * Marks the keyboard-selected slot with a two-tone ring outside its edge, so the ring reads against any bar color.
6288
6275
  *
@@ -6323,8 +6310,7 @@ const SelectedBarRing = ({ chartId, selected, slotKeys, groupPadding, horizontal
6323
6310
  testId: "bar-chart-selected-ring"
6324
6311
  });
6325
6312
  };
6326
- //#endregion
6327
- //#region src/charts/bar-chart/private/bar-layer.tsx
6313
+ // src/charts/bar-chart/private/bar-layer.tsx
6328
6314
  /**
6329
6315
  * Draws the bars in front of any comparison shadows, slotted for an overlap layout and grouped by visx otherwise, then the selected bar's ring.
6330
6316
  *
@@ -6392,8 +6378,7 @@ const BarLayer = ({ chartId, overlapSlots, selectedBar, primaryEntries, primaryK
6392
6378
  yAccessor
6393
6379
  })] });
6394
6380
  };
6395
- //#endregion
6396
- //#region src/charts/bar-chart/private/slot-tooltip-members.tsx
6381
+ // src/charts/bar-chart/private/slot-tooltip-members.tsx
6397
6382
  /**
6398
6383
  * Fills the tooltip with every bar of the keyboard-selected category, and only those.
6399
6384
  *
@@ -6401,26 +6386,20 @@ const BarLayer = ({ chartId, overlapSlots, selectedBar, primaryEntries, primaryK
6401
6386
  *
6402
6387
  * @param props - Component props.
6403
6388
  * @param props.members - The category's bars, the keyboard stop last.
6404
- * @param props.index - The selected data point.
6405
6389
  * @return No visual content.
6406
6390
  */
6407
- function SlotTooltipMembers({ members, index }) {
6391
+ function SlotTooltipMembers({ members }) {
6408
6392
  const { showTooltip, updateTooltip } = useContext(TooltipContext) ?? {};
6409
6393
  useEffect(() => {
6410
6394
  updateTooltip?.((state) => ({
6411
6395
  ...state,
6412
6396
  tooltipData: void 0
6413
6397
  }));
6414
- members.forEach(({ key, datum }) => showTooltip?.({
6415
- key,
6416
- datum,
6417
- index
6418
- }));
6419
- }, [members, index]);
6398
+ members.forEach((member) => showTooltip?.(member));
6399
+ }, [members]);
6420
6400
  return null;
6421
6401
  }
6422
- //#endregion
6423
- //#region src/charts/bar-chart/private/overlap-bars.ts
6402
+ // src/charts/bar-chart/private/overlap-bars.ts
6424
6403
  const PRIMARY_SLOT = "primary";
6425
6404
  const COMPARISON_SLOT = "comparison";
6426
6405
  const OVERLAP_SLOTS = [PRIMARY_SLOT, COMPARISON_SLOT];
@@ -6528,8 +6507,7 @@ function getOverlapBarColors(series, colors, slotColors, background) {
6528
6507
  });
6529
6508
  return barColors;
6530
6509
  }
6531
- //#endregion
6532
- //#region src/charts/bar-chart/private/use-overlap-slots.ts
6510
+ // src/charts/bar-chart/private/use-overlap-slots.ts
6533
6511
  /**
6534
6512
  * Whether two data points sit at the same category: the same label, or the same date.
6535
6513
  *
@@ -6538,7 +6516,7 @@ function getOverlapBarColors(series, colors, slotColors, background) {
6538
6516
  * @return Whether `point` is at `category`.
6539
6517
  */
6540
6518
  function isSameCategory(point, category) {
6541
- return category.label != null ? point.label === category.label : !!category.date && !!point.date && point.date.getTime() === category.date.getTime();
6519
+ return category.label ? point.label === category.label : !!category.date && !!point.date && point.date.getTime() === category.date.getTime();
6542
6520
  }
6543
6521
  /**
6544
6522
  * Lays out the visible series of an overlap layout in slots and layers.
@@ -6583,7 +6561,7 @@ function useOverlapSlots(enabled, seriesWithVisibility) {
6583
6561
  * @return The category key.
6584
6562
  */
6585
6563
  function categoryKey(point) {
6586
- return point.label != null ? `label:${point.label}` : `date:${point.date?.getTime()}`;
6564
+ return point.label ? `label:${point.label}` : `date:${point.date?.getTime()}`;
6587
6565
  }
6588
6566
  /**
6589
6567
  * Lists a stop for every slot at every category that slot draws a bar at, category by category.
@@ -6621,6 +6599,25 @@ function getStopPositions(entries, slotKeys, slotOf) {
6621
6599
  }));
6622
6600
  }
6623
6601
  /**
6602
+ * Every bar at a category, each with its own data point index, the keyboard stop last.
6603
+ *
6604
+ * @param entries - The visible series.
6605
+ * @param category - The data point naming the category.
6606
+ * @param stopKey - The series the keyboard stop is on.
6607
+ * @return The category's bars; the last one shown becomes the tooltip's nearest datum.
6608
+ */
6609
+ function membersAt(entries, category, stopKey) {
6610
+ const members = entries.flatMap(({ series }) => {
6611
+ const index = series.data.findIndex((point) => isSameCategory(point, category));
6612
+ return index === -1 ? [] : [{
6613
+ key: series.label,
6614
+ datum: series.data[index],
6615
+ index
6616
+ }];
6617
+ });
6618
+ return [...members.filter(({ key }) => key !== stopKey), ...members.filter(({ key }) => key === stopKey)];
6619
+ }
6620
+ /**
6624
6621
  * The slot a keyboard index selects, and every bar at its category.
6625
6622
  *
6626
6623
  * @param slots - The overlap layout.
@@ -6630,25 +6627,17 @@ function getStopPositions(entries, slotKeys, slotOf) {
6630
6627
  function getSelectedSlot(slots, selectedIndex) {
6631
6628
  const position = selectedIndex === void 0 ? void 0 : slots?.positions[selectedIndex];
6632
6629
  if (!slots || !position) return;
6633
- const { slotKey, key: stopKey, datum: category, dataPointIndex } = position;
6634
- const members = slots.entries.flatMap(({ series }) => {
6635
- const datum = series.data.find((point) => isSameCategory(point, category));
6636
- return datum ? [{
6637
- key: series.label,
6638
- datum
6639
- }] : [];
6640
- });
6630
+ const { slotKey, key: stopKey, datum: category } = position;
6631
+ const members = membersAt(slots.entries, category, stopKey);
6641
6632
  const slotBars = members.filter(({ key, datum }) => isBarRendered(datum) && slots.slotOf(key) === slotKey);
6642
6633
  return {
6643
6634
  data: slotBars.map(({ datum }) => datum),
6644
6635
  slotKey,
6645
6636
  thickness: Math.max(...slotBars.map(({ key }) => slots.thicknessOf(key))),
6646
- index: dataPointIndex,
6647
- members: [...members.filter(({ key }) => key !== stopKey), ...members.filter(({ key }) => key === stopKey)]
6637
+ members
6648
6638
  };
6649
6639
  }
6650
- //#endregion
6651
- //#region src/charts/bar-chart/private/use-bar-stops.ts
6640
+ // src/charts/bar-chart/private/use-bar-stops.ts
6652
6641
  /**
6653
6642
  * Lays out the keyboard stops: one per slot and category in an overlap layout, else one per primary bar, series-major within each category.
6654
6643
  *
@@ -6660,7 +6649,6 @@ function useBarStops(overlapSlots, primaryEntries) {
6660
6649
  const series = useMemo(() => overlapSlots ? [] : primaryEntries.map((entry) => entry.series), [overlapSlots, primaryEntries]);
6661
6650
  return {
6662
6651
  count: overlapSlots?.positions.length ?? Math.max(0, ...series.map((item) => item.data.length)) * series.length,
6663
- series,
6664
6652
  key: useMemo(() => JSON.stringify(overlapSlots?.keys ?? series.map((item) => item.label)), [overlapSlots, series]),
6665
6653
  barAt: useCallback((stop) => {
6666
6654
  if (overlapSlots) {
@@ -6703,8 +6691,7 @@ const MAX_GROUP_PADDING = .9;
6703
6691
  * gap between ticks. `0.75` = a 25% reduction of the tick-gap padding.
6704
6692
  */
6705
6693
  const COMPARISON_TICK_GAP_FACTOR = .75;
6706
- //#endregion
6707
- //#region src/charts/bar-chart/private/comparison-bars.tsx
6694
+ // src/charts/bar-chart/private/comparison-bars.tsx
6708
6695
  const ComparisonBars = ({ comparisonEntries, primaryKeys, groupPadding, horizontal, xAccessor, yAccessor, getElementStyles, resolveFill }) => {
6709
6696
  const context = useContext(DataContext);
6710
6697
  const xScale = context?.xScale;
@@ -6763,8 +6750,7 @@ const ComparisonBars = ({ comparisonEntries, primaryKeys, groupPadding, horizont
6763
6750
  children: rects
6764
6751
  });
6765
6752
  };
6766
- //#endregion
6767
- //#region src/charts/bar-chart/private/band-highlight.tsx
6753
+ // src/charts/bar-chart/private/band-highlight.tsx
6768
6754
  /**
6769
6755
  * Render and report the active band using the chart’s registered scales.
6770
6756
  * @param root0 - Highlight options.
@@ -6823,8 +6809,7 @@ function BandHighlight({ visible, horizontal, onChange }) {
6823
6809
  fill: CATALOG_POINTERS.surfaceSecondary
6824
6810
  });
6825
6811
  }
6826
- //#endregion
6827
- //#region src/charts/bar-chart/private/band-tooltip.tsx
6812
+ // src/charts/bar-chart/private/band-tooltip.tsx
6828
6813
  /**
6829
6814
  * Find a category by its painted center, including outer padding and reversed ranges.
6830
6815
  * @param data - Registered series points.
@@ -6943,8 +6928,7 @@ function BandTooltip({ keys, slots, groupPadding, withTooltips, onPointerDown, o
6943
6928
  useEventEmitter("pointerup", onPointerUp ? handlePointer : void 0);
6944
6929
  return null;
6945
6930
  }
6946
- //#endregion
6947
- //#region src/charts/bar-chart/private/grouped-bars.ts
6931
+ // src/charts/bar-chart/private/grouped-bars.ts
6948
6932
  /**
6949
6933
  * Pairs each comparison series with the primary of its `group`, or with the only primary.
6950
6934
  *
@@ -6984,8 +6968,7 @@ function getGroupedBarColors(series, colors, background) {
6984
6968
  });
6985
6969
  return barColors;
6986
6970
  }
6987
- //#endregion
6988
- //#region src/charts/bar-chart/use-bar-colors.ts
6971
+ // src/charts/bar-chart/use-bar-colors.ts
6989
6972
  /**
6990
6973
  * Reads the colors `BarChart` fills series with, so a custom tooltip or legend can match the bars.
6991
6974
  *
@@ -7007,8 +6990,7 @@ function useBarColors() {
7007
6990
  comparisonOpacity
7008
6991
  ]);
7009
6992
  }
7010
- //#endregion
7011
- //#region src/charts/bar-chart/use-bar-legend-items.ts
6993
+ // src/charts/bar-chart/use-bar-legend-items.ts
7012
6994
  const isComparison = (data, label) => data.some((series) => series.label === label && series.options?.type === "comparison");
7013
6995
  /**
7014
6996
  * Applies what a bar layout changes about a legend: overlap lists every primary before every comparison, as it draws their slots, with every swatch opaque like its bar; a collapsed grouped item takes its comparison's tint, the wider bar that frames the group.
@@ -7072,8 +7054,7 @@ function useBarLegendItems(data, options = {}, legendShape) {
7072
7054
  seriesColors
7073
7055
  ]);
7074
7056
  }
7075
- //#endregion
7076
- //#region src/charts/bar-chart/bar-chart.tsx
7057
+ // src/charts/bar-chart/bar-chart.tsx
7077
7058
  const validateData$2 = (data) => {
7078
7059
  if (!data?.length) return __("No data available", "jetpack-charts");
7079
7060
  if (data.some((series) => series.data.some((point) => isInvalidReading(point.value, { allowMissing: true }) || !point.label && (!("date" in point && point.date) || isNaN(point.date.getTime()))))) return __("Invalid data", "jetpack-charts");
@@ -7264,10 +7245,7 @@ const BarChartInternal = ({ data, ariaLabel, chartId: providedChartId, width, he
7264
7245
  const primaryKey = tooltipData?.nearestDatum?.key;
7265
7246
  const categoryLabel = chartOptions.tooltip.labelFormatter(nearestDatum.label || (nearestDatum.date ? nearestDatum.date.getTime() : 0), 0, []);
7266
7247
  const comparisonEntry = comparisonEntries.find((entry) => entry.primaryKey === primaryKey);
7267
- const comparisonDatum = comparisonEntry?.series.data.find((point) => {
7268
- const p = point;
7269
- return nearestDatum.label != null ? p.label === nearestDatum.label : !!nearestDatum.date && !!p.date && p.date.getTime() === nearestDatum.date.getTime();
7270
- });
7248
+ const comparisonDatum = comparisonEntry?.series.data.find((point) => isSameCategory(point, nearestDatum));
7271
7249
  if (comparisonEntry && comparisonDatum) return /* @__PURE__ */ jsxs("div", {
7272
7250
  className: bar_chart_module_default["bar-chart__tooltip"],
7273
7251
  children: [
@@ -7337,6 +7315,17 @@ const BarChartInternal = ({ data, ariaLabel, chartId: providedChartId, width, he
7337
7315
  slotOf: overlapSlots.slotOf
7338
7316
  }, [overlapSlots]);
7339
7317
  const selectedSlot = useMemo(() => getSelectedSlot(overlapSlots, selectedIndex), [overlapSlots, selectedIndex]);
7318
+ const selectedGroup = useMemo(() => {
7319
+ const stop = overlapSlots || selectedIndex === void 0 ? void 0 : barAt(selectedIndex);
7320
+ if (!stop) return;
7321
+ return membersAt(primaryEntries, stop.datum, stop.key);
7322
+ }, [
7323
+ overlapSlots,
7324
+ selectedIndex,
7325
+ barAt,
7326
+ primaryEntries
7327
+ ]);
7328
+ const selectedMembers = selectedSlot?.members ?? selectedGroup;
7340
7329
  const selectedBar = useMemo(() => {
7341
7330
  if (overlapSlots) return selectedSlot;
7342
7331
  const bar = selectedIndex === void 0 ? void 0 : barAt(selectedIndex);
@@ -7499,10 +7488,7 @@ const BarChartInternal = ({ data, ariaLabel, chartId: providedChartId, width, he
7499
7488
  ...!horizontal && valueTicks ? { tickValues: valueTicks } : {}
7500
7489
  })] })
7501
7490
  }),
7502
- withTooltips && selectedSlot && /* @__PURE__ */ jsx(SlotTooltipMembers, {
7503
- members: selectedSlot.members,
7504
- index: selectedSlot.index
7505
- }),
7491
+ withTooltips && selectedMembers && /* @__PURE__ */ jsx(SlotTooltipMembers, { members: selectedMembers }),
7506
7492
  withTooltips && /* @__PURE__ */ jsx(XYChartTooltip, {
7507
7493
  tooltipPlacement,
7508
7494
  tooltipAnchorTop,
@@ -7514,7 +7500,6 @@ const BarChartInternal = ({ data, ariaLabel, chartId: providedChartId, width, he
7514
7500
  selectedIndex,
7515
7501
  tooltipRef,
7516
7502
  keyboardFocusedClassName: bar_chart_module_default["bar-chart__tooltip--keyboard-focused"],
7517
- series: stops.series,
7518
7503
  mode: "individual"
7519
7504
  })
7520
7505
  ]
@@ -7532,8 +7517,7 @@ const BarChartWithProvider = (props) => {
7532
7517
  BarChartWithProvider.displayName = "BarChart";
7533
7518
  const BarChart = attachSubComponents(BarChartWithProvider, { Legend });
7534
7519
  const BarChartResponsive = attachSubComponents(withResponsive(BarChartWithProvider), { Legend });
7535
- //#endregion
7536
- //#region src/charts/bar-list-chart/bar-list-chart.tsx
7520
+ // src/charts/bar-list-chart/bar-list-chart.tsx
7537
7521
  /**
7538
7522
  * Get the bandwidth of a scale
7539
7523
  * @param scale - The scale to get the bandwidth of
@@ -7702,8 +7686,7 @@ const BarListChart = (props) => {
7702
7686
  };
7703
7687
  BarListChart.displayName = "BarListChart";
7704
7688
  const BarListChartResponsive = withResponsive(BarListChart);
7705
- //#endregion
7706
- //#region src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
7689
+ // src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss
7707
7690
  var conversion_funnel_chart_module_default = {
7708
7691
  "bar-container": "a8ccharts-mGEVca-bar-container",
7709
7692
  "change-indicator": "a8ccharts-mGEVca-change-indicator",
@@ -7722,83 +7705,131 @@ var conversion_funnel_chart_module_default = {
7722
7705
  "main-rate": "a8ccharts-mGEVca-main-rate",
7723
7706
  "step-label": "a8ccharts-mGEVca-step-label",
7724
7707
  "step-rate": "a8ccharts-mGEVca-step-rate",
7708
+ "step-text": "a8ccharts-mGEVca-step-text",
7725
7709
  "stretch": "a8ccharts-mGEVca-stretch",
7726
- "tooltip-content": "a8ccharts-mGEVca-tooltip-content",
7727
- "tooltip-title": "a8ccharts-mGEVca-tooltip-title"
7710
+ "tooltip-label": "a8ccharts-mGEVca-tooltip-label",
7711
+ "tooltip-title": "a8ccharts-mGEVca-tooltip-title",
7712
+ "tooltip-value": "a8ccharts-mGEVca-tooltip-value"
7728
7713
  };
7729
- //#endregion
7730
- //#region src/charts/conversion-funnel-chart/private/use-funnel-selection.ts
7714
+ // src/charts/conversion-funnel-chart/private/use-funnel-selection.ts
7731
7715
  /**
7732
- * Custom hook to manage funnel bar selection state and interactions
7716
+ * Custom hook to manage funnel step selection state
7733
7717
  * @param hideTooltip - Function to hide tooltip when selection is cleared
7734
- * @return Object containing selection state and event handlers
7718
+ * @return Object containing selection state and its setters
7735
7719
  */
7736
7720
  const useFunnelSelection = (hideTooltip) => {
7737
- const [clickedStep, setClickedStep] = useState(null);
7721
+ const [selectedStepId, setSelectedStepId] = useState(null);
7738
7722
  return {
7739
- clickedStep,
7740
- handleBarClick: useCallback((stepId) => {
7741
- if (clickedStep === stepId) {
7742
- setClickedStep(null);
7743
- hideTooltip?.();
7744
- } else setClickedStep(stepId);
7745
- }, [clickedStep, hideTooltip]),
7746
- handleBarKeyDown: useCallback((stepId, event) => {
7747
- if (event.key === "Enter" || event.key === " ") {
7748
- event.preventDefault();
7749
- if (clickedStep === stepId) {
7750
- setClickedStep(null);
7751
- hideTooltip?.();
7752
- } else setClickedStep(stepId);
7753
- } else if (event.key === "Escape") {
7754
- event.preventDefault();
7755
- setClickedStep(null);
7756
- hideTooltip?.();
7757
- }
7758
- }, [clickedStep, hideTooltip]),
7723
+ selectedStepId,
7724
+ selectStep: setSelectedStepId,
7759
7725
  clearSelection: useCallback(() => {
7760
- setClickedStep(null);
7726
+ setSelectedStepId(null);
7761
7727
  hideTooltip?.();
7762
7728
  }, [hideTooltip]),
7763
7729
  getStepState: useCallback((stepId) => ({
7764
- isClicked: clickedStep === stepId,
7765
- isBlurred: clickedStep !== null && clickedStep !== stepId
7766
- }), [clickedStep])
7730
+ isSelected: selectedStepId === stepId,
7731
+ isBlurred: selectedStepId !== null && selectedStepId !== stepId
7732
+ }), [selectedStepId])
7733
+ };
7734
+ };
7735
+ // src/charts/conversion-funnel-chart/private/use-roving-step-focus.ts
7736
+ const getTargetIndex = (key, index, count, isRtl) => {
7737
+ const nextKey = isRtl ? "ArrowLeft" : "ArrowRight";
7738
+ const previousKey = isRtl ? "ArrowRight" : "ArrowLeft";
7739
+ switch (key) {
7740
+ case nextKey: return Math.min(index + 1, count - 1);
7741
+ case previousKey: return Math.max(index - 1, 0);
7742
+ case "Home": return 0;
7743
+ case "End": return count - 1;
7744
+ default: return;
7745
+ }
7746
+ };
7747
+ /**
7748
+ * Roving tabindex for the funnel steps: one Tab stop, and arrow keys, Home and End move focus between steps.
7749
+ *
7750
+ * @param stepIds - Step ids in visual order.
7751
+ * @param selectedStepId - The selected step, which holds the Tab stop until any step has taken focus.
7752
+ * @return Tab index, element registration, focus and key handlers for each step.
7753
+ */
7754
+ const useRovingStepFocus = (stepIds, selectedStepId) => {
7755
+ const [focusedStepId, setFocusedStepId] = useState(null);
7756
+ const stepElements = useRef(/* @__PURE__ */ new Map());
7757
+ const tabStopId = [focusedStepId, selectedStepId].find((id) => id !== null && stepIds.includes(id)) ?? stepIds[0];
7758
+ return {
7759
+ getTabIndex: useCallback((stepId) => stepId === tabStopId ? 0 : -1, [tabStopId]),
7760
+ setStepElement: useCallback((stepId, element) => {
7761
+ if (element) stepElements.current.set(stepId, element);
7762
+ else stepElements.current.delete(stepId);
7763
+ }, []),
7764
+ handleStepFocus: useCallback((stepId) => {
7765
+ setFocusedStepId(stepId);
7766
+ }, []),
7767
+ handleNavigationKey: useCallback((stepId, event) => {
7768
+ if (event.altKey || event.ctrlKey || event.metaKey) return false;
7769
+ const isRtl = getComputedStyle(event.currentTarget).direction === "rtl";
7770
+ const targetIndex = getTargetIndex(event.key, stepIds.indexOf(stepId), stepIds.length, isRtl);
7771
+ if (targetIndex === void 0) return false;
7772
+ event.preventDefault();
7773
+ stepElements.current.get(stepIds[targetIndex])?.focus();
7774
+ return true;
7775
+ }, [stepIds])
7767
7776
  };
7768
7777
  };
7769
- //#endregion
7770
- //#region src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx
7778
+ // src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx
7771
7779
  /** Chart height (px) below which the funnel tightens its gaps so the bars keep their room. */
7772
7780
  const SHORT_CHART_HEIGHT = 180;
7781
+ const formatStepCount = (count) => sprintf(_n("%s item", "%s items", count, "jetpack-charts"), formatMetricValue(count));
7782
+ const getDefaultTooltipContent = (step) => ({
7783
+ value: step.count === void 0 ? void 0 : formatStepCount(step.count),
7784
+ rows: [{
7785
+ label: __("Conversion rate", "jetpack-charts"),
7786
+ value: formatPercentage(step.rate)
7787
+ }]
7788
+ });
7789
+ const getDefaultTooltipIds = (tooltipId, { rows = [] }) => ({
7790
+ value: `${tooltipId}-value`,
7791
+ rows: rows.map((_, index) => ({
7792
+ label: `${tooltipId}-row-${index}-label`,
7793
+ value: `${tooltipId}-row-${index}-value`
7794
+ }))
7795
+ });
7796
+ const getDefaultTooltipDescriptionIds = (tooltipId, content) => {
7797
+ const ids = getDefaultTooltipIds(tooltipId, content);
7798
+ return [...content.value ? [ids.value] : [], ...ids.rows.flatMap((row) => [row.label, row.value])].join(" ");
7799
+ };
7773
7800
  /**
7774
7801
  * Internal ConversionFunnelChart component with chart registration
7775
7802
  *
7776
- * @param props - Component props
7777
- * @param props.chartId - Optional unique identifier for the chart
7778
- * @param props.mainRate - Main conversion rate to highlight
7779
- * @param props.changeIndicator - Change indicator (e.g., +2%, -1.5%)
7780
- * @param props.steps - Array of funnel steps
7781
- * @param props.loading - Whether the chart is in loading state
7782
- * @param props.animation - Whether to show chart animation on initial render or not
7783
- * @param props.className - Additional CSS class name
7784
- * @param props.ariaLabel - Accessible name for the chart group
7785
- * @param props.height - Height of the chart container. Falls back to style.height if set, otherwise defaults to "100%".
7786
- * @param props.style - Custom styling
7787
- * @param props.renderStepLabel - Custom render function for step labels
7788
- * @param props.renderStepRate - Custom render function for step rates
7789
- * @param props.renderMainMetric - Custom render function for the entire main metric section
7790
- * @param props.renderTooltip - Custom render function for tooltip content
7791
- * @param props.tooltipStyle - Inline styles merged over the tooltip box defaults
7803
+ * @param props - Component props
7804
+ * @param props.chartId - Optional unique identifier for the chart
7805
+ * @param props.mainRate - Main conversion rate to highlight
7806
+ * @param props.changeIndicator - Change indicator (e.g., +2%, -1.5%)
7807
+ * @param props.steps - Array of funnel steps
7808
+ * @param props.loading - Whether the chart is in loading state
7809
+ * @param props.animation - Whether to show chart animation on initial render or not
7810
+ * @param props.className - Additional CSS class name
7811
+ * @param props.ariaLabel - Accessible name for the chart group
7812
+ * @param props.height - Height of the chart container. Falls back to style.height if set, otherwise defaults to "100%".
7813
+ * @param props.style - Custom styling
7814
+ * @param props.renderStepLabel - Custom render function for step labels
7815
+ * @param props.renderStepRate - Custom render function for step rates
7816
+ * @param props.renderMainMetric - Custom render function for the entire main metric section
7817
+ * @param props.renderTooltip - Custom render function for tooltip content
7818
+ * @param props.tooltipStyle - Inline styles merged over the tooltip box defaults
7819
+ * @param props.getTooltipContent - What each step's tooltip shows, which screen readers also read
7792
7820
  * @return JSX element representing the conversion funnel chart
7793
7821
  */
7794
- const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loading = false, animation, className, ariaLabel, chartId: providedChartId, height, style, renderStepLabel, renderStepRate, renderMainMetric, renderTooltip, tooltipStyle }) => {
7822
+ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loading = false, animation, className, ariaLabel, chartId: providedChartId, height, style, renderStepLabel, renderStepRate, renderMainMetric, renderTooltip, tooltipStyle, getTooltipContent = getDefaultTooltipContent }) => {
7795
7823
  const chartId = useChartId(providedChartId);
7796
7824
  const { getElementStyles, isColorPaletteResolved } = useGlobalChartsContext();
7797
7825
  const chartRef = useRef(null);
7798
- const selectedBarRef = useRef(null);
7826
+ const isPointerFocusRef = useRef(false);
7799
7827
  const [scopeNode, setScopeNode] = useState(null);
7828
+ const tooltipId = useId();
7800
7829
  const { tooltipData, tooltipLeft, tooltipTop, tooltipOpen, showTooltip, hideTooltip } = useTooltip();
7801
- const { handleBarClick, handleBarKeyDown, clearSelection, getStepState } = useFunnelSelection(hideTooltip);
7830
+ const { selectedStepId, selectStep, clearSelection, getStepState } = useFunnelSelection(hideTooltip);
7831
+ const stepIds = useMemo(() => steps?.map((step) => step.id) ?? [], [steps]);
7832
+ const { getTabIndex, setStepElement, handleStepFocus, handleNavigationKey } = useRovingStepFocus(stepIds, selectedStepId);
7802
7833
  const standaloneScopeClass = useStandaloneScopeClass();
7803
7834
  const [measureChartRef, , chartHeight] = useElementSize();
7804
7835
  const gap = chartHeight > 0 && chartHeight < SHORT_CHART_HEIGHT ? "sm" : "xl";
@@ -7807,94 +7838,71 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
7807
7838
  setScopeNode(node);
7808
7839
  measureChartRef(node);
7809
7840
  }, [measureChartRef]);
7810
- const clearSelectionAndRef = useCallback(() => {
7811
- clearSelection();
7812
- selectedBarRef.current = null;
7813
- hideTooltip();
7814
- }, [clearSelection, hideTooltip]);
7815
- const showTooltipAt = useCallback((step, x, y) => {
7816
- showTooltip({
7841
+ const selectStepAt = useCallback((step, x, y) => {
7842
+ selectStep(step.id);
7843
+ const bounds = chartRef.current?.getBoundingClientRect();
7844
+ if (bounds) showTooltip({
7817
7845
  tooltipData: step,
7818
- tooltipLeft: x,
7819
- tooltipTop: y - 10
7846
+ tooltipLeft: x - bounds.left,
7847
+ tooltipTop: y - bounds.top - 10
7820
7848
  });
7821
- }, [showTooltip]);
7822
- const getMouseTooltipCoords = useCallback((event) => {
7823
- const bounds = chartRef.current?.getBoundingClientRect();
7824
- if (!bounds) return null;
7825
- return {
7826
- x: event.clientX - bounds.left,
7827
- y: event.clientY - bounds.top
7828
- };
7829
- }, []);
7830
- const getKeyboardTooltipCoords = useCallback((event) => {
7831
- const bounds = chartRef.current?.getBoundingClientRect();
7832
- if (!bounds) return null;
7833
- const rect = event.currentTarget.getBoundingClientRect();
7834
- return {
7835
- x: rect.left + rect.width / 2 - bounds.left,
7836
- y: rect.top - bounds.top
7837
- };
7838
- }, []);
7839
- const handleStepInteraction = useCallback((step, event, interactionType) => {
7840
- selectedBarRef.current = event.currentTarget;
7841
- const { isClicked } = getStepState(step.id);
7842
- if (isClicked) {
7843
- if (interactionType === "click") handleBarClick(step.id);
7844
- else handleBarKeyDown(step.id, event);
7845
- return;
7846
- }
7847
- if (interactionType === "click") {
7848
- handleBarClick(step.id);
7849
- const coords = getMouseTooltipCoords(event);
7850
- if (coords) showTooltipAt(step, coords.x, coords.y);
7851
- } else {
7852
- handleBarKeyDown(step.id, event);
7853
- const coords = getKeyboardTooltipCoords(event);
7854
- if (coords) showTooltipAt(step, coords.x, coords.y);
7855
- }
7856
- }, [
7857
- getStepState,
7858
- handleBarClick,
7859
- handleBarKeyDown,
7860
- showTooltipAt,
7861
- getMouseTooltipCoords,
7862
- getKeyboardTooltipCoords
7863
- ]);
7849
+ }, [selectStep, showTooltip]);
7850
+ const selectStepAtElement = useCallback((step, element) => {
7851
+ const rect = element.getBoundingClientRect();
7852
+ selectStepAt(step, rect.left + rect.width / 2, rect.top);
7853
+ }, [selectStepAt]);
7864
7854
  const stepHandlers = useMemo(() => {
7865
7855
  const handlers = /* @__PURE__ */ new Map();
7866
7856
  steps.forEach((step) => {
7857
+ const onPointerDown = () => {
7858
+ isPointerFocusRef.current = true;
7859
+ };
7867
7860
  const onClick = (event) => {
7868
- event.stopPropagation();
7869
- handleStepInteraction(step, event, "click");
7861
+ isPointerFocusRef.current = false;
7862
+ selectStepAt(step, event.clientX, event.clientY);
7863
+ };
7864
+ const onFocus = (event) => {
7865
+ handleStepFocus(step.id);
7866
+ if (isPointerFocusRef.current) isPointerFocusRef.current = false;
7867
+ else if (step.id !== selectedStepId) selectStepAtElement(step, event.currentTarget);
7870
7868
  };
7871
7869
  const onKeyDown = (event) => {
7872
- if (event.key === "Enter" || event.key === " ") handleStepInteraction(step, event, "keyboard");
7873
- else {
7874
- selectedBarRef.current = event.currentTarget;
7875
- handleBarKeyDown(step.id, event);
7870
+ isPointerFocusRef.current = false;
7871
+ if (handleNavigationKey(step.id, event)) return;
7872
+ if (event.key === "Enter" || event.key === " ") {
7873
+ event.preventDefault();
7874
+ selectStepAtElement(step, event.currentTarget);
7875
+ } else if (event.key === "Escape" && selectedStepId !== null) {
7876
+ event.preventDefault();
7877
+ clearSelection();
7876
7878
  }
7877
7879
  };
7880
+ const ref = (element) => setStepElement(step.id, element);
7878
7881
  handlers.set(step.id, {
7882
+ onPointerDown,
7879
7883
  onClick,
7880
- onKeyDown
7884
+ onKeyDown,
7885
+ onFocus,
7886
+ ref
7881
7887
  });
7882
7888
  });
7883
7889
  return handlers;
7884
7890
  }, [
7885
7891
  steps,
7886
- handleStepInteraction,
7887
- handleBarKeyDown
7892
+ selectedStepId,
7893
+ selectStepAt,
7894
+ selectStepAtElement,
7895
+ clearSelection,
7896
+ handleNavigationKey,
7897
+ handleStepFocus,
7898
+ setStepElement
7888
7899
  ]);
7889
- useEffect(() => {
7890
- const handleDocumentClick = (event) => {
7891
- if (selectedBarRef.current && !selectedBarRef.current.contains(event.target)) clearSelectionAndRef();
7892
- };
7893
- document.addEventListener("mousedown", handleDocumentClick);
7894
- return () => {
7895
- document.removeEventListener("mousedown", handleDocumentClick);
7896
- };
7897
- }, [clearSelectionAndRef]);
7900
+ const handleStepsBlur = useCallback((event) => {
7901
+ if (!event.currentTarget.contains(event.relatedTarget) && document.hasFocus()) {
7902
+ isPointerFocusRef.current = false;
7903
+ clearSelection();
7904
+ }
7905
+ }, [clearSelection]);
7898
7906
  const resolvedHeight = height ?? style?.height ?? "100%";
7899
7907
  const { color: barColor } = getElementStyles ? getElementStyles({ index: 0 }) : { color: "#000000" };
7900
7908
  const isPositiveChange = changeIndicator?.startsWith("+");
@@ -7906,18 +7914,41 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
7906
7914
  className: clsx(conversion_funnel_chart_module_default["change-indicator"], conversion_funnel_chart_module_default[isPositiveChange ? "change-indicator--positive" : "change-indicator--negative"]),
7907
7915
  children: changeIndicator
7908
7916
  })] });
7909
- const renderDefaultTooltip = (step) => /* @__PURE__ */ jsxs(Stack, {
7910
- direction: "column",
7911
- align: "flex-start",
7912
- gap: "xs",
7913
- children: [/* @__PURE__ */ jsx("div", {
7914
- className: conversion_funnel_chart_module_default["tooltip-title"],
7915
- children: step.label
7916
- }), /* @__PURE__ */ jsxs("div", {
7917
- className: conversion_funnel_chart_module_default["tooltip-content"],
7918
- children: [formatPercentage(step.rate), ` • ${step.count ?? "no"} items`]
7919
- })]
7920
- });
7917
+ const renderDefaultTooltip = (step, content) => {
7918
+ const ids = getDefaultTooltipIds(tooltipId, content);
7919
+ return /* @__PURE__ */ jsxs(Stack, {
7920
+ direction: "column",
7921
+ gap: "xs",
7922
+ children: [/* @__PURE__ */ jsxs(Stack, {
7923
+ direction: "row",
7924
+ justify: "space-between",
7925
+ align: "baseline",
7926
+ gap: "sm",
7927
+ children: [/* @__PURE__ */ jsx("span", {
7928
+ className: conversion_funnel_chart_module_default["tooltip-title"],
7929
+ children: step.label
7930
+ }), content.value && /* @__PURE__ */ jsx("span", {
7931
+ id: ids.value,
7932
+ className: conversion_funnel_chart_module_default["tooltip-value"],
7933
+ children: content.value
7934
+ })]
7935
+ }), content.rows?.map((row, index) => /* @__PURE__ */ jsxs(Stack, {
7936
+ direction: "row",
7937
+ justify: "space-between",
7938
+ align: "baseline",
7939
+ gap: "sm",
7940
+ children: [/* @__PURE__ */ jsx("span", {
7941
+ id: ids.rows[index].label,
7942
+ className: conversion_funnel_chart_module_default["tooltip-label"],
7943
+ children: row.label
7944
+ }), /* @__PURE__ */ jsx("span", {
7945
+ id: ids.rows[index].value,
7946
+ className: conversion_funnel_chart_module_default["tooltip-value"],
7947
+ children: row.value
7948
+ })]
7949
+ }, row.label))]
7950
+ });
7951
+ };
7921
7952
  const isDataValid = Boolean(steps && steps.length > 0);
7922
7953
  const chartMetadata = useMemo(() => ({
7923
7954
  mainRate,
@@ -7952,6 +7983,26 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
7952
7983
  })
7953
7984
  });
7954
7985
  const maxRate = Math.max(...steps.map((step) => step.rate));
7986
+ const tooltipStep = tooltipOpen ? tooltipData : void 0;
7987
+ let tooltipContent = null;
7988
+ let tooltipDescriptionIds = "";
7989
+ if (tooltipStep) {
7990
+ const index = steps.findIndex((s) => s.id === tooltipStep.id);
7991
+ const content = getTooltipContent(tooltipStep, index);
7992
+ if (renderTooltip) {
7993
+ tooltipContent = renderTooltip({
7994
+ step: tooltipStep,
7995
+ index,
7996
+ content,
7997
+ top: tooltipTop,
7998
+ left: tooltipLeft
7999
+ });
8000
+ tooltipDescriptionIds = tooltipId;
8001
+ } else {
8002
+ tooltipContent = renderDefaultTooltip(tooltipStep, content);
8003
+ tooltipDescriptionIds = getDefaultTooltipDescriptionIds(tooltipId, content);
8004
+ }
8005
+ }
7955
8006
  return /* @__PURE__ */ jsxs(Stack, {
7956
8007
  direction: "column",
7957
8008
  gap,
@@ -7980,10 +8031,16 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
7980
8031
  direction: "row",
7981
8032
  align: "flex-end",
7982
8033
  gap: "lg",
8034
+ role: "listbox",
8035
+ "aria-label": __("Funnel steps", "jetpack-charts"),
8036
+ "aria-orientation": "horizontal",
8037
+ onBlur: handleStepsBlur,
7983
8038
  className: conversion_funnel_chart_module_default["funnel-container"],
7984
8039
  children: steps.map((step, index) => {
7985
8040
  const barHeight = step.rate / maxRate * 100;
7986
- const { isBlurred } = getStepState(step.id);
8041
+ const { isSelected, isBlurred } = getStepState(step.id);
8042
+ const handlers = stepHandlers.get(step.id);
8043
+ const isDescribedByTooltip = Boolean(tooltipContent && tooltipDescriptionIds) && tooltipStep?.id === step.id;
7987
8044
  return /* @__PURE__ */ jsxs(Stack, {
7988
8045
  direction: "column",
7989
8046
  className: clsx(conversion_funnel_chart_module_default["funnel-step"], isColorPaletteResolved && conversion_funnel_chart_module_default["funnel-step--animated"], isBlurred && conversion_funnel_chart_module_default["funnel-step--blurred"]),
@@ -7991,6 +8048,8 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
7991
8048
  children: [/* @__PURE__ */ jsxs(Stack, {
7992
8049
  direction: "column",
7993
8050
  gap: "xs",
8051
+ className: conversion_funnel_chart_module_default["step-text"],
8052
+ "aria-hidden": "true",
7994
8053
  children: [renderStepLabel ? renderStepLabel({
7995
8054
  step,
7996
8055
  index,
@@ -8010,11 +8069,16 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
8010
8069
  direction: "column",
8011
8070
  justify: "flex-end",
8012
8071
  className: conversion_funnel_chart_module_default["bar-container"],
8013
- onClick: stepHandlers.get(step.id)?.onClick,
8014
- onKeyDown: stepHandlers.get(step.id)?.onKeyDown,
8015
- role: "button",
8016
- tabIndex: isBlurred ? -1 : 0,
8017
- "aria-label": step.label,
8072
+ ref: handlers?.ref,
8073
+ onPointerDown: handlers?.onPointerDown,
8074
+ onClick: handlers?.onClick,
8075
+ onKeyDown: handlers?.onKeyDown,
8076
+ onFocus: handlers?.onFocus,
8077
+ role: "option",
8078
+ tabIndex: getTabIndex(step.id),
8079
+ "aria-label": sprintf(__("%1$s, %2$s", "jetpack-charts"), step.label, formatPercentage(step.rate)),
8080
+ "aria-selected": isSelected,
8081
+ "aria-describedby": isDescribedByTooltip ? tooltipDescriptionIds : void 0,
8018
8082
  children: /* @__PURE__ */ jsx("div", {
8019
8083
  className: clsx(conversion_funnel_chart_module_default["funnel-bar"], { [conversion_funnel_chart_module_default["funnel-bar--animated"]]: animation && !loading && !prefersReducedMotion }),
8020
8084
  style: {
@@ -8026,25 +8090,17 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
8026
8090
  }, step.id);
8027
8091
  })
8028
8092
  })]
8029
- }), tooltipOpen && tooltipData && (() => {
8030
- const tooltipContent = renderTooltip ? renderTooltip({
8031
- step: tooltipData,
8032
- index: steps.findIndex((s) => s.id === tooltipData.id),
8033
- top: tooltipTop,
8034
- left: tooltipLeft
8035
- }) : renderDefaultTooltip(tooltipData);
8036
- if (!tooltipContent) return null;
8037
- return /* @__PURE__ */ jsx(BoundedTooltip, {
8038
- top: tooltipTop,
8039
- left: tooltipLeft,
8040
- className: standaloneScopeClass,
8041
- style: tooltipStyle,
8042
- children: /* @__PURE__ */ jsx("div", {
8043
- role: "tooltip",
8044
- children: tooltipContent
8045
- })
8046
- });
8047
- })()]
8093
+ }), tooltipContent && /* @__PURE__ */ jsx(BoundedTooltip, {
8094
+ top: tooltipTop,
8095
+ left: tooltipLeft,
8096
+ className: standaloneScopeClass,
8097
+ style: tooltipStyle,
8098
+ children: /* @__PURE__ */ jsx("div", {
8099
+ id: tooltipId,
8100
+ "aria-hidden": "true",
8101
+ children: tooltipContent
8102
+ })
8103
+ })]
8048
8104
  });
8049
8105
  };
8050
8106
  /**
@@ -8058,8 +8114,7 @@ const ConversionFunnelChartWithProvider = (props) => {
8058
8114
  return /* @__PURE__ */ jsx(GlobalChartsProvider, { children: /* @__PURE__ */ jsx(ConversionFunnelChartInternal, { ...props }) });
8059
8115
  };
8060
8116
  ConversionFunnelChartWithProvider.displayName = "ConversionFunnelChart";
8061
- //#endregion
8062
- //#region src/utils/sanitize-html.ts
8117
+ // src/utils/sanitize-html.ts
8063
8118
  /**
8064
8119
  * External dependencies
8065
8120
  */
@@ -8107,11 +8162,9 @@ function sanitizeHtml(html) {
8107
8162
  ]
8108
8163
  });
8109
8164
  }
8110
- //#endregion
8111
- //#region src/charts/geo-chart/geo-chart.module.scss
8165
+ // src/charts/geo-chart/geo-chart.module.scss
8112
8166
  var geo_chart_module_default = { "container": "a8ccharts-8hS2IW-container" };
8113
- //#endregion
8114
- //#region src/charts/geo-chart/private/use-tooltip-position.ts
8167
+ // src/charts/geo-chart/private/use-tooltip-position.ts
8115
8168
  const TOOLTIP_CLASS = "google-visualization-tooltip";
8116
8169
  const isTooltip = (node) => node instanceof HTMLElement && node.classList.contains(TOOLTIP_CLASS);
8117
8170
  /**
@@ -8195,8 +8248,7 @@ function useTooltipPosition(containerRef) {
8195
8248
  };
8196
8249
  }, [containerRef]);
8197
8250
  }
8198
- //#endregion
8199
- //#region src/charts/geo-chart/geo-chart.tsx
8251
+ // src/charts/geo-chart/geo-chart.tsx
8200
8252
  /**
8201
8253
  * External dependencies
8202
8254
  */
@@ -8416,8 +8468,7 @@ const GeoChartWithProvider = (props) => {
8416
8468
  };
8417
8469
  GeoChartWithProvider.displayName = "GeoChart";
8418
8470
  const GeoChartResponsive = withResponsive(GeoChartWithProvider);
8419
- //#endregion
8420
- //#region src/types.ts
8471
+ // src/types.ts
8421
8472
  let GoogleDataTableColumnRoleType = /* @__PURE__ */ function(GoogleDataTableColumnRoleType) {
8422
8473
  GoogleDataTableColumnRoleType["annotation"] = "annotation";
8423
8474
  GoogleDataTableColumnRoleType["annotationText"] = "annotationText";
@@ -8497,8 +8548,7 @@ const pickLabelTextColor = (fill, roles, defaultRole) => {
8497
8548
  if (!isValidHexColor(fillHex)) return defaultRole;
8498
8549
  return pickLabelTextColorForFill(hexToRgb(fillHex), roles, defaultRole);
8499
8550
  };
8500
- //#endregion
8501
- //#region src/charts/heatmap-chart/heatmap-chart.module.scss
8551
+ // src/charts/heatmap-chart/heatmap-chart.module.scss
8502
8552
  var heatmap_chart_module_default = {
8503
8553
  "heatmap-chart": "a8ccharts-O3YMOW-heatmap-chart",
8504
8554
  "heatmap-chart__cell": "a8ccharts-O3YMOW-heatmap-chart__cell",
@@ -8529,8 +8579,7 @@ var heatmap_chart_module_default = {
8529
8579
  "heatmap-chart__row-label": "a8ccharts-O3YMOW-heatmap-chart__row-label",
8530
8580
  "heatmap-chart--height-capped": "a8ccharts-O3YMOW-heatmap-chart--height-capped"
8531
8581
  };
8532
- //#endregion
8533
- //#region src/charts/heatmap-chart/private/use-heatmap-colors.ts
8582
+ // src/charts/heatmap-chart/private/use-heatmap-colors.ts
8534
8583
  const isPresent = (value) => value !== null && value !== void 0 && !isNaN(value);
8535
8584
  /**
8536
8585
  * Get the min and max values from heatmap data, ignoring null/NaN and the zeros
@@ -8609,12 +8658,10 @@ const getHeatmapScale = (primary, background, emptyCell) => {
8609
8658
  high
8610
8659
  };
8611
8660
  };
8612
- //#endregion
8613
- //#region src/charts/heatmap-chart/private/heatmap-context.ts
8661
+ // src/charts/heatmap-chart/private/heatmap-context.ts
8614
8662
  /** Shared by the chart and legend without importing back from `heatmap-chart.tsx`. */
8615
8663
  const HeatmapContext = createContext(null);
8616
- //#endregion
8617
- //#region src/charts/heatmap-chart/private/heatmap-legend.tsx
8664
+ // src/charts/heatmap-chart/private/heatmap-legend.tsx
8618
8665
  const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }) => {
8619
8666
  const context = useContext(HeatmapContext);
8620
8667
  const { legend } = useGlobalChartsTheme();
@@ -8658,8 +8705,7 @@ const HeatmapLegend = ({ steps = 5, variant = "swatches", lessLabel, moreLabel }
8658
8705
  ]
8659
8706
  });
8660
8707
  };
8661
- //#endregion
8662
- //#region src/charts/heatmap-chart/private/column-groups.ts
8708
+ // src/charts/heatmap-chart/private/column-groups.ts
8663
8709
  const isSpan = (span) => Number.isInteger(span) && span > 0;
8664
8710
  /**
8665
8711
  * Validates column groups and lays them over the columns.
@@ -8765,8 +8811,7 @@ const wrapColumnGroups = (layout, bands) => {
8765
8811
  slotSpans
8766
8812
  };
8767
8813
  };
8768
- //#endregion
8769
- //#region src/charts/heatmap-chart/private/fit-compact-cells.ts
8814
+ // src/charts/heatmap-chart/private/fit-compact-cells.ts
8770
8815
  /**
8771
8816
  * Largest whole-pixel square cell, and the band count giving it, for a compact grid in a box.
8772
8817
  *
@@ -8804,8 +8849,7 @@ const fitCompactCells = (input) => {
8804
8849
  cellSize: minCellSize
8805
8850
  };
8806
8851
  };
8807
- //#endregion
8808
- //#region src/charts/heatmap-chart/private/keyboard-navigation.ts
8852
+ // src/charts/heatmap-chart/private/keyboard-navigation.ts
8809
8853
  const ARROW_KEYS = [
8810
8854
  "ArrowLeft",
8811
8855
  "ArrowRight",
@@ -8935,8 +8979,7 @@ const stepCalendarCell = (grid, blocks, from, key) => {
8935
8979
  const before = page.slice(0, at === -1 ? page.length : at).reverse();
8936
8980
  return firstSelectable(grid, after) ?? firstSelectable(grid, before);
8937
8981
  };
8938
- //#endregion
8939
- //#region src/charts/heatmap-chart/heatmap-chart.tsx
8982
+ // src/charts/heatmap-chart/heatmap-chart.tsx
8940
8983
  const CELL_VALUE_MODIFIER = {
8941
8984
  label: void 0,
8942
8985
  "label-inverse": heatmap_chart_module_default["heatmap-chart__cell-value--inverse"],
@@ -9391,8 +9434,7 @@ const HeatmapChartResponsiveInner = (props) => /* @__PURE__ */ jsx(HeatmapChartW
9391
9434
  });
9392
9435
  HeatmapChartResponsiveInner.displayName = "HeatmapChart";
9393
9436
  const HeatmapChartResponsive = attachSubComponents(withResponsive(HeatmapChartResponsiveInner), { Legend: HeatmapLegend });
9394
- //#endregion
9395
- //#region src/charts/heatmap-chart/private/civil-day.ts
9437
+ // src/charts/heatmap-chart/private/civil-day.ts
9396
9438
  const DAY_MS = 864e5;
9397
9439
  const KEY_OPTIONS = {
9398
9440
  calendar: "gregory",
@@ -9541,8 +9583,7 @@ const startOfCivilWeek = (date, weekStartsOn) => {
9541
9583
  * @return Columns needed to cover the span, inclusive.
9542
9584
  */
9543
9585
  const civilWeekSpan = (from, to, weekStartsOn) => Math.floor((startOfCivilWeek(to, weekStartsOn).getTime() - startOfCivilWeek(from, weekStartsOn).getTime()) / (7 * DAY_MS)) + 1;
9544
- //#endregion
9545
- //#region src/charts/heatmap-chart/build-calendar-data.ts
9586
+ // src/charts/heatmap-chart/build-calendar-data.ts
9546
9587
  /** Rows that get a weekday label (Mon, Wed, Fri with a Monday week start). */
9547
9588
  const LABELLED_ROWS = [
9548
9589
  0,
@@ -9644,8 +9685,7 @@ const buildCalendarHeatmapData = (series, options = {}) => {
9644
9685
  rowLabels
9645
9686
  };
9646
9687
  };
9647
- //#endregion
9648
- //#region src/charts/heatmap-chart/build-month-calendar-data.ts
9688
+ // src/charts/heatmap-chart/build-month-calendar-data.ts
9649
9689
  /** Week rows per month, fixed so every month block is the same height. */
9650
9690
  const MONTH_ROWS = 6;
9651
9691
  const DAYS_PER_WEEK = 7;
@@ -9727,8 +9767,7 @@ const buildMonthCalendarHeatmapData = (valueByDay, range, options = {}) => {
9727
9767
  columnGroups
9728
9768
  };
9729
9769
  };
9730
- //#endregion
9731
- //#region src/charts/heatmap-chart/use-calendar-heatmap-data.ts
9770
+ // src/charts/heatmap-chart/use-calendar-heatmap-data.ts
9732
9771
  /**
9733
9772
  * `buildCalendarHeatmapData` with the locale and zone taken from
9734
9773
  * `GlobalChartsProvider` where the caller names neither.
@@ -9763,8 +9802,7 @@ const useCalendarHeatmapData = (series, options = {}) => {
9763
9802
  gridEnd
9764
9803
  ]);
9765
9804
  };
9766
- //#endregion
9767
- //#region src/charts/heatmap-chart/use-month-calendar-heatmap-data.ts
9805
+ // src/charts/heatmap-chart/use-month-calendar-heatmap-data.ts
9768
9806
  /**
9769
9807
  * `buildMonthCalendarHeatmapData` with the locale taken from `GlobalChartsProvider`
9770
9808
  * where the caller names none.
@@ -9793,8 +9831,7 @@ const useMonthCalendarHeatmapData = (valueByDay, range, options = {}) => {
9793
9831
  weekStartsOn
9794
9832
  ]);
9795
9833
  };
9796
- //#endregion
9797
- //#region ../../../node_modules/.pnpm/is-plain-object@5.1.0/node_modules/is-plain-object/dist/is-plain-object.mjs
9834
+ // ../../../node_modules/.pnpm/is-plain-object@5.1.0/node_modules/is-plain-object/dist/is-plain-object.mjs
9798
9835
  /*!
9799
9836
  * is-plain-object <https://github.com/jonschlinkert/is-plain-object>
9800
9837
  *
@@ -9814,16 +9851,14 @@ function isPlainObject(o) {
9814
9851
  if (prot.hasOwnProperty("isPrototypeOf") === false) return false;
9815
9852
  return true;
9816
9853
  }
9817
- //#endregion
9818
- //#region ../../../node_modules/.pnpm/lower-case@2.0.2/node_modules/lower-case/dist.es2015/index.js
9854
+ // ../../../node_modules/.pnpm/lower-case@2.0.2/node_modules/lower-case/dist.es2015/index.js
9819
9855
  /**
9820
9856
  * Lower case as a function.
9821
9857
  */
9822
9858
  function lowerCase(str) {
9823
9859
  return str.toLowerCase();
9824
9860
  }
9825
- //#endregion
9826
- //#region ../../../node_modules/.pnpm/no-case@3.0.4/node_modules/no-case/dist.es2015/index.js
9861
+ // ../../../node_modules/.pnpm/no-case@3.0.4/node_modules/no-case/dist.es2015/index.js
9827
9862
  var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
9828
9863
  var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
9829
9864
  /**
@@ -9848,23 +9883,19 @@ function replace$1(input, re, value) {
9848
9883
  return input.replace(re, value);
9849
9884
  }, input);
9850
9885
  }
9851
- //#endregion
9852
- //#region ../../../node_modules/.pnpm/dot-case@3.0.4/node_modules/dot-case/dist.es2015/index.js
9886
+ // ../../../node_modules/.pnpm/dot-case@3.0.4/node_modules/dot-case/dist.es2015/index.js
9853
9887
  function dotCase(input, options) {
9854
9888
  if (options === void 0) options = {};
9855
9889
  return noCase(input, __assign({ delimiter: "." }, options));
9856
9890
  }
9857
- //#endregion
9858
- //#region ../../../node_modules/.pnpm/param-case@3.0.4/node_modules/param-case/dist.es2015/index.js
9891
+ // ../../../node_modules/.pnpm/param-case@3.0.4/node_modules/param-case/dist.es2015/index.js
9859
9892
  function paramCase(input, options) {
9860
9893
  if (options === void 0) options = {};
9861
9894
  return dotCase(input, __assign({ delimiter: "-" }, options));
9862
9895
  }
9863
- //#endregion
9864
- //#region ../../../node_modules/.pnpm/@wordpress+warning@3.57.0/node_modules/@wordpress/warning/build-module/utils.mjs
9896
+ // ../../../node_modules/.pnpm/@wordpress+warning@3.57.0/node_modules/@wordpress/warning/build-module/utils.mjs
9865
9897
  var logged = /* @__PURE__ */ new Set();
9866
- //#endregion
9867
- //#region ../../../node_modules/.pnpm/@wordpress+warning@3.57.0/node_modules/@wordpress/warning/build-module/index.mjs
9898
+ // ../../../node_modules/.pnpm/@wordpress+warning@3.57.0/node_modules/@wordpress/warning/build-module/index.mjs
9868
9899
  function isDev() {
9869
9900
  return globalThis.SCRIPT_DEBUG === true;
9870
9901
  }
@@ -9877,8 +9908,7 @@ function warning(message) {
9877
9908
  } catch {}
9878
9909
  logged.add(message);
9879
9910
  }
9880
- //#endregion
9881
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/hooks/use-update-effect.mjs
9911
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/hooks/use-update-effect.mjs
9882
9912
  function useUpdateEffect(effect, deps) {
9883
9913
  const mountedRef = useRef$1(false);
9884
9914
  useEffect$1(() => {
@@ -9890,8 +9920,7 @@ function useUpdateEffect(effect, deps) {
9890
9920
  }, []);
9891
9921
  }
9892
9922
  var use_update_effect_default = useUpdateEffect;
9893
- //#endregion
9894
- //#region ../../../node_modules/.pnpm/@emotion+sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js
9923
+ // ../../../node_modules/.pnpm/@emotion+sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js
9895
9924
  function sheetForTag(tag) {
9896
9925
  if (tag.sheet) return tag.sheet;
9897
9926
  /* istanbul ignore next */
@@ -9953,8 +9982,7 @@ var StyleSheet = /*#__PURE__*/ function() {
9953
9982
  };
9954
9983
  return StyleSheet;
9955
9984
  }();
9956
- //#endregion
9957
- //#region ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js
9985
+ // ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js
9958
9986
  var MS = "-ms-";
9959
9987
  var MOZ = "-moz-";
9960
9988
  var WEBKIT = "-webkit-";
@@ -9964,8 +9992,7 @@ var DECLARATION = "decl";
9964
9992
  var IMPORT = "@import";
9965
9993
  var KEYFRAMES = "@keyframes";
9966
9994
  var LAYER = "@layer";
9967
- //#endregion
9968
- //#region ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js
9995
+ // ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js
9969
9996
  /**
9970
9997
  * @param {number}
9971
9998
  * @return {number}
@@ -10068,8 +10095,7 @@ function append(value, array) {
10068
10095
  function combine(array, callback) {
10069
10096
  return array.map(callback).join("");
10070
10097
  }
10071
- //#endregion
10072
- //#region ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js
10098
+ // ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js
10073
10099
  var line = 1;
10074
10100
  var column = 1;
10075
10101
  var length = 0;
@@ -10255,8 +10281,7 @@ function identifier(index) {
10255
10281
  while (!token(peek())) next();
10256
10282
  return slice(index, position);
10257
10283
  }
10258
- //#endregion
10259
- //#region ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js
10284
+ // ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js
10260
10285
  /**
10261
10286
  * @param {string} value
10262
10287
  * @return {object[]}
@@ -10409,8 +10434,7 @@ function comment(value, root, parent) {
10409
10434
  function declaration(value, root, parent, length) {
10410
10435
  return node(value, root, parent, DECLARATION, substr(value, 0, length), substr(value, length + 1, -1), length);
10411
10436
  }
10412
- //#endregion
10413
- //#region ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js
10437
+ // ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js
10414
10438
  /**
10415
10439
  * @param {object[]} children
10416
10440
  * @param {function} callback
@@ -10440,8 +10464,7 @@ function stringify(element, index, children, callback) {
10440
10464
  }
10441
10465
  return strlen(children = serialize(element.children, callback)) ? element.return = element.value + "{" + children + "}" : "";
10442
10466
  }
10443
- //#endregion
10444
- //#region ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js
10467
+ // ../../../node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js
10445
10468
  /**
10446
10469
  * @param {function[]} collection
10447
10470
  * @return {function}
@@ -10465,8 +10488,7 @@ function rulesheet(callback) {
10465
10488
  }
10466
10489
  };
10467
10490
  }
10468
- //#endregion
10469
- //#region ../../../node_modules/.pnpm/@emotion+memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js
10491
+ // ../../../node_modules/.pnpm/@emotion+memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js
10470
10492
  function memoize(fn) {
10471
10493
  var cache = Object.create(null);
10472
10494
  return function(arg) {
@@ -10474,8 +10496,7 @@ function memoize(fn) {
10474
10496
  return cache[arg];
10475
10497
  };
10476
10498
  }
10477
- //#endregion
10478
- //#region ../../../node_modules/.pnpm/@emotion+cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js
10499
+ // ../../../node_modules/.pnpm/@emotion+cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js
10479
10500
  var identifierWithPointTracking = function identifierWithPointTracking(begin, points, index) {
10480
10501
  var previous = 0;
10481
10502
  var character = 0;
@@ -10701,8 +10722,7 @@ var createCache = function createCache(options) {
10701
10722
  cache.sheet.hydrate(nodesToHydrate);
10702
10723
  return cache;
10703
10724
  };
10704
- //#endregion
10705
- //#region ../../../node_modules/.pnpm/@emotion+utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js
10725
+ // ../../../node_modules/.pnpm/@emotion+utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js
10706
10726
  function getRegisteredStyles$1(registered, registeredStyles, classNames) {
10707
10727
  var rawClassName = "";
10708
10728
  classNames.split(" ").forEach(function(className) {
@@ -10726,8 +10746,7 @@ var insertStyles = function insertStyles(cache, serialized, isStringTag) {
10726
10746
  } while (current !== void 0);
10727
10747
  }
10728
10748
  };
10729
- //#endregion
10730
- //#region ../../../node_modules/.pnpm/@emotion+hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js
10749
+ // ../../../node_modules/.pnpm/@emotion+hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js
10731
10750
  function murmur2(str) {
10732
10751
  var h = 0;
10733
10752
  var k, i = 0, len = str.length;
@@ -10748,8 +10767,7 @@ function murmur2(str) {
10748
10767
  h = (h & 65535) * 1540483477 + ((h >>> 16) * 59797 << 16);
10749
10768
  return ((h ^ h >>> 15) >>> 0).toString(36);
10750
10769
  }
10751
- //#endregion
10752
- //#region ../../../node_modules/.pnpm/@emotion+unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js
10770
+ // ../../../node_modules/.pnpm/@emotion+unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js
10753
10771
  var unitlessKeys = {
10754
10772
  animationIterationCount: 1,
10755
10773
  aspectRatio: 1,
@@ -10799,8 +10817,7 @@ var unitlessKeys = {
10799
10817
  strokeOpacity: 1,
10800
10818
  strokeWidth: 1
10801
10819
  };
10802
- //#endregion
10803
- //#region ../../../node_modules/.pnpm/@emotion+serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js
10820
+ // ../../../node_modules/.pnpm/@emotion+serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js
10804
10821
  var isDevelopment = false;
10805
10822
  var hyphenateRegex = /[A-Z]|^ms/g;
10806
10823
  var animationRegex = /_EMO_([^_]+?)_([^]*?)_EMO_/g;
@@ -10925,16 +10942,14 @@ function serializeStyles(args, registered, mergedProps) {
10925
10942
  };
10926
10943
  }
10927
10944
  React["useInsertionEffect"] && React["useInsertionEffect"] || React.useLayoutEffect;
10928
- //#endregion
10929
- //#region ../../../node_modules/.pnpm/@emotion+react@11.14.0_@types+react@19.3.0_react@19.3.0/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js
10945
+ // ../../../node_modules/.pnpm/@emotion+react@11.14.0_@types+react@19.3.0_react@19.3.0/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js
10930
10946
  var EmotionCacheContext = /* #__PURE__ */ React.createContext(typeof HTMLElement !== "undefined" ? /* #__PURE__ */ createCache({ key: "css" }) : null);
10931
10947
  EmotionCacheContext.Provider;
10932
10948
  var __unsafe_useEmotionCache = function useEmotionCache() {
10933
10949
  return useContext(EmotionCacheContext);
10934
10950
  };
10935
10951
  ({}).hasOwnProperty;
10936
- //#endregion
10937
- //#region ../../../node_modules/.pnpm/@emotion+css@11.13.5/node_modules/@emotion/css/create-instance/dist/emotion-css-create-instance.esm.js
10952
+ // ../../../node_modules/.pnpm/@emotion+css@11.13.5/node_modules/@emotion/css/create-instance/dist/emotion-css-create-instance.esm.js
10938
10953
  function insertWithoutScoping(cache, serialized) {
10939
10954
  if (cache.inserted[serialized.name] === void 0) return cache.insert("", serialized, cache.sheet, true);
10940
10955
  }
@@ -11019,8 +11034,7 @@ var classnames = function classnames(args) {
11019
11034
  }
11020
11035
  return cls;
11021
11036
  };
11022
- //#endregion
11023
- //#region ../../../node_modules/.pnpm/@emotion+css@11.13.5/node_modules/@emotion/css/dist/emotion-css.esm.js
11037
+ // ../../../node_modules/.pnpm/@emotion+css@11.13.5/node_modules/@emotion/css/dist/emotion-css.esm.js
11024
11038
  var _createEmotion = createEmotion({ key: "css" });
11025
11039
  _createEmotion.flush;
11026
11040
  _createEmotion.hydrate;
@@ -11032,8 +11046,7 @@ _createEmotion.keyframes;
11032
11046
  _createEmotion.css;
11033
11047
  _createEmotion.sheet;
11034
11048
  _createEmotion.cache;
11035
- //#endregion
11036
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/hooks/use-cx.mjs
11049
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/hooks/use-cx.mjs
11037
11050
  var isSerializedStyles = (o) => typeof o !== "undefined" && o !== null && ["name", "styles"].every((p) => typeof o[p] !== "undefined");
11038
11051
  var useCx = () => {
11039
11052
  const cache = __unsafe_useEmotionCache();
@@ -11048,8 +11061,7 @@ var useCx = () => {
11048
11061
  }));
11049
11062
  }, [cache]);
11050
11063
  };
11051
- //#endregion
11052
- //#region ../../../node_modules/.pnpm/memize@2.1.1/node_modules/memize/dist/index.js
11064
+ // ../../../node_modules/.pnpm/memize@2.1.1/node_modules/memize/dist/index.js
11053
11065
  /**
11054
11066
  * Memize options object.
11055
11067
  *
@@ -11139,8 +11151,7 @@ function memize(fn, options) {
11139
11151
  };
11140
11152
  return memoized;
11141
11153
  }
11142
- //#endregion
11143
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/context-system-provider.mjs
11154
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/context-system-provider.mjs
11144
11155
  var import_es6 = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
11145
11156
  module.exports = function equal(a, b) {
11146
11157
  if (a === b) return true;
@@ -11207,19 +11218,16 @@ var BaseContextSystemProvider = ({ children, value }) => {
11207
11218
  });
11208
11219
  };
11209
11220
  memo(BaseContextSystemProvider);
11210
- //#endregion
11211
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/constants.mjs
11221
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/constants.mjs
11212
11222
  var COMPONENT_NAMESPACE = "data-wp-component";
11213
11223
  var CONNECTED_NAMESPACE = "data-wp-c16t";
11214
11224
  var CONNECT_STATIC_NAMESPACE = "__contextSystemKey__";
11215
- //#endregion
11216
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/get-styled-class-name-from-key.mjs
11225
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/get-styled-class-name-from-key.mjs
11217
11226
  function getStyledClassName(namespace) {
11218
11227
  return `components-${paramCase(namespace)}`;
11219
11228
  }
11220
11229
  var getStyledClassNameFromKey = memize(getStyledClassName);
11221
- //#endregion
11222
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/context-connect.mjs
11230
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/context-connect.mjs
11223
11231
  function contextConnect(Component, namespace) {
11224
11232
  return _contextConnect(Component, namespace, { forwardsRef: true });
11225
11233
  }
@@ -11235,16 +11243,14 @@ function _contextConnect(Component, namespace, options) {
11235
11243
  selector: `.${getStyledClassNameFromKey(namespace)}`
11236
11244
  });
11237
11245
  }
11238
- //#endregion
11239
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/utils.mjs
11246
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/utils.mjs
11240
11247
  function getNamespace(componentName) {
11241
11248
  return { [COMPONENT_NAMESPACE]: componentName };
11242
11249
  }
11243
11250
  function getConnectedNamespace() {
11244
11251
  return { [CONNECTED_NAMESPACE]: true };
11245
11252
  }
11246
- //#endregion
11247
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/use-context-system.mjs
11253
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/context/use-context-system.mjs
11248
11254
  function useContextSystem(props, namespace) {
11249
11255
  const contextSystemProps = useComponentsContext();
11250
11256
  if (typeof namespace === "undefined") globalThis.SCRIPT_DEBUG === true && warning("useContextSystem: Please provide a namespace");
@@ -11265,8 +11271,7 @@ function useContextSystem(props, namespace) {
11265
11271
  finalComponentProps.className = classes;
11266
11272
  return finalComponentProps;
11267
11273
  }
11268
- //#endregion
11269
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/visually-hidden/styles.mjs
11274
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/visually-hidden/styles.mjs
11270
11275
  var visuallyHidden = {
11271
11276
  border: 0,
11272
11277
  clip: "rect(1px, 1px, 1px, 1px)",
@@ -11281,8 +11286,7 @@ var visuallyHidden = {
11281
11286
  wordWrap: "normal",
11282
11287
  wordBreak: "normal"
11283
11288
  };
11284
- //#endregion
11285
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/polymorphic-element.mjs
11289
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/polymorphic-element.mjs
11286
11290
  var customAttributeRegExp = /^(data|aria|x)-/i;
11287
11291
  var eventHandlerRegExp = /^on[A-Z]/;
11288
11292
  var svgElementNames = new Set(`animate animateMotion animateTransform circle clipPath defs desc ellipse
@@ -11371,8 +11375,7 @@ function UnforwardedPolymorphicElement({ as, ...props }, ref) {
11371
11375
  });
11372
11376
  }
11373
11377
  var PolymorphicElement = forwardRef$1(UnforwardedPolymorphicElement);
11374
- //#endregion
11375
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/view/component.mjs
11378
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/view/component.mjs
11376
11379
  function UnforwardedView({ css, ...restProps }, ref) {
11377
11380
  return /* @__PURE__ */ jsx(PolymorphicElement, {
11378
11381
  ref,
@@ -11380,8 +11383,7 @@ function UnforwardedView({ css, ...restProps }, ref) {
11380
11383
  });
11381
11384
  }
11382
11385
  var component_default$2 = Object.assign(forwardRef$1(UnforwardedView), { selector: ".components-view" });
11383
- //#endregion
11384
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/visually-hidden/component.mjs
11386
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/visually-hidden/component.mjs
11385
11387
  function UnconnectedVisuallyHidden(props, forwardedRef) {
11386
11388
  const { style: styleProp, ...contextProps } = useContextSystem(props, "VisuallyHidden");
11387
11389
  return /* @__PURE__ */ jsx(component_default$2, {
@@ -11395,8 +11397,7 @@ function UnconnectedVisuallyHidden(props, forwardedRef) {
11395
11397
  });
11396
11398
  }
11397
11399
  var component_default$1 = contextConnect(UnconnectedVisuallyHidden, "VisuallyHidden");
11398
- //#endregion
11399
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/use-responsive-value.mjs
11400
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/utils/use-responsive-value.mjs
11400
11401
  var breakpoints = [
11401
11402
  "40em",
11402
11403
  "52em",
@@ -11434,8 +11435,7 @@ function useResponsiveValue(values, options = {}) {
11434
11435
  const array = values || [];
11435
11436
  return array[index >= array.length ? array.length - 1 : index];
11436
11437
  }
11437
- //#endregion
11438
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/grid/utils.mjs
11438
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/grid/utils.mjs
11439
11439
  var ALIGNMENTS = {
11440
11440
  bottom: {
11441
11441
  alignItems: "flex-end",
@@ -11482,8 +11482,7 @@ var ALIGNMENTS = {
11482
11482
  function getAlignmentProps(alignment) {
11483
11483
  return alignment ? ALIGNMENTS[alignment] ?? {} : {};
11484
11484
  }
11485
- //#endregion
11486
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/grid/hook.mjs
11485
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/grid/hook.mjs
11487
11486
  var STYLE_HASH_ATTRIBUTE = "data-wp-hash";
11488
11487
  function getRuntime() {
11489
11488
  const globalScope = globalThis;
@@ -11627,8 +11626,7 @@ function useGrid(props) {
11627
11626
  }
11628
11627
  };
11629
11628
  }
11630
- //#endregion
11631
- //#region ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/grid/component.mjs
11629
+ // ../../../node_modules/.pnpm/@wordpress+components@42.0.0_@date-fns+tz@1.5.0_@types+react-dom@19.3.0_@types+react@19_6d0393a58a031b78f608040e2ecbe6e0/node_modules/@wordpress/components/build-module/grid/component.mjs
11632
11630
  function UnconnectedGrid(props, forwardedRef) {
11633
11631
  const gridProps = useGrid(props);
11634
11632
  return /* @__PURE__ */ jsx(component_default$2, {
@@ -11637,8 +11635,7 @@ function UnconnectedGrid(props, forwardedRef) {
11637
11635
  });
11638
11636
  }
11639
11637
  var component_default = contextConnect(UnconnectedGrid, "Grid");
11640
- //#endregion
11641
- //#region src/charts/leaderboard-chart/hooks/use-fitted-row-count.ts
11638
+ // src/charts/leaderboard-chart/hooks/use-fitted-row-count.ts
11642
11639
  /**
11643
11640
  * Fractional layout rounding can put a row's bottom a hair past the container's
11644
11641
  * without any visible clipping. Allow that much slack before hiding a row.
@@ -11721,8 +11718,7 @@ function useFittedRowCount(enabled, rowCount, data) {
11721
11718
  isMeasurable
11722
11719
  };
11723
11720
  }
11724
- //#endregion
11725
- //#region src/charts/leaderboard-chart/hooks/use-leaderboard-legend-items.ts
11721
+ // src/charts/leaderboard-chart/hooks/use-leaderboard-legend-items.ts
11726
11722
  /**
11727
11723
  * Hook to create legend items from leaderboard data
11728
11724
  * @param root0 - Configuration object
@@ -11770,11 +11766,12 @@ function useLeaderboardLegendItems({ data, primaryColor, secondaryColor, withCom
11770
11766
  withOverlayLabel
11771
11767
  ]);
11772
11768
  }
11773
- //#endregion
11774
- //#region src/charts/leaderboard-chart/leaderboard-chart.module.scss
11769
+ // src/charts/leaderboard-chart/leaderboard-chart.module.scss
11775
11770
  var leaderboard_chart_module_default = {
11776
11771
  "bar": "a8ccharts-GovfoW-bar",
11777
11772
  "bar--animated": "a8ccharts-GovfoW-bar--animated",
11773
+ "bar--negative": "a8ccharts-GovfoW-bar--negative",
11774
+ "barTrack": "a8ccharts-GovfoW-barTrack",
11778
11775
  "barWithLabelContainer": "a8ccharts-GovfoW-barWithLabelContainer",
11779
11776
  "chevron": "a8ccharts-GovfoW-chevron",
11780
11777
  "deltaPlaceholder": "a8ccharts-GovfoW-deltaPlaceholder",
@@ -11801,8 +11798,7 @@ var leaderboard_chart_module_default = {
11801
11798
  "stretch": "a8ccharts-GovfoW-stretch",
11802
11799
  "valueContainer": "a8ccharts-GovfoW-valueContainer"
11803
11800
  };
11804
- //#endregion
11805
- //#region src/charts/leaderboard-chart/leaderboard-chart.tsx
11801
+ // src/charts/leaderboard-chart/leaderboard-chart.tsx
11806
11802
  const ROW_GAP = "var(--a8c-charts-dimension-leaderboard-row-gap, 12px)";
11807
11803
  const COLUMN_GAP = "var(--a8c-charts-dimension-leaderboard-column-gap, 4px)";
11808
11804
  /** Indexed by `Math.sign( delta ) + 1`, so [negative, neutral, positive]. */
@@ -11862,27 +11858,43 @@ const BarLabel = ({ label }) => /* @__PURE__ */ jsx(Fragment$1, { children: type
11862
11858
  className: leaderboard_chart_module_default.label,
11863
11859
  children: label
11864
11860
  }) : label });
11865
- const BarWithLabel = ({ entry, withComparison, withOverlayLabel, primaryColor, secondaryColor, animation, isPrimaryVisible = true, isComparisonVisible = true }) => {
11861
+ const Bar = ({ share, color, animation, divergingScale }) => {
11862
+ const isNegative = share < 0;
11863
+ const sideMax = divergingScale?.[isNegative ? "negative" : "positive"];
11864
+ const width = sideMax ? Math.abs(share) / sideMax * 100 : Math.abs(share);
11865
+ const bar = /* @__PURE__ */ jsx("div", {
11866
+ className: clsx(leaderboard_chart_module_default.bar, {
11867
+ [leaderboard_chart_module_default["bar--animated"]]: animation,
11868
+ [leaderboard_chart_module_default["bar--negative"]]: divergingScale && isNegative
11869
+ }),
11870
+ style: {
11871
+ width: getBarWidth(width),
11872
+ backgroundColor: color
11873
+ }
11874
+ });
11875
+ if (!divergingScale) return bar;
11876
+ return /* @__PURE__ */ jsx("div", {
11877
+ className: leaderboard_chart_module_default.barTrack,
11878
+ style: { gridTemplateColumns: `${divergingScale.negative}fr ${divergingScale.positive}fr` },
11879
+ children: bar
11880
+ });
11881
+ };
11882
+ const BarWithLabel = ({ entry, withComparison, withOverlayLabel, primaryColor, secondaryColor, animation, divergingScale, isPrimaryVisible = true, isComparisonVisible = true }) => {
11866
11883
  const showComparisonBar = withComparison && !withOverlayLabel && isComparisonVisible;
11884
+ const bars = /* @__PURE__ */ jsxs(Fragment$1, { children: [isPrimaryVisible && /* @__PURE__ */ jsx(Bar, {
11885
+ share: entry.currentShare,
11886
+ color: primaryColor,
11887
+ animation,
11888
+ divergingScale
11889
+ }), showComparisonBar && hasPreviousValue(entry) && /* @__PURE__ */ jsx(Bar, {
11890
+ share: entry.previousShare,
11891
+ color: secondaryColor,
11892
+ animation,
11893
+ divergingScale
11894
+ })] });
11867
11895
  return /* @__PURE__ */ jsxs("div", {
11868
11896
  className: clsx(leaderboard_chart_module_default.barWithLabelContainer, { [leaderboard_chart_module_default["is-overlay"]]: withOverlayLabel }),
11869
- children: [
11870
- /* @__PURE__ */ jsx(BarLabel, { label: entry.label }),
11871
- isPrimaryVisible && /* @__PURE__ */ jsx("div", {
11872
- className: clsx(leaderboard_chart_module_default.bar, { [leaderboard_chart_module_default["bar--animated"]]: animation }),
11873
- style: {
11874
- width: getBarWidth(entry.currentShare),
11875
- backgroundColor: primaryColor
11876
- }
11877
- }),
11878
- showComparisonBar && hasPreviousValue(entry) && /* @__PURE__ */ jsx("div", {
11879
- className: clsx(leaderboard_chart_module_default.bar, { [leaderboard_chart_module_default["bar--animated"]]: animation }),
11880
- style: {
11881
- width: getBarWidth(entry.previousShare),
11882
- backgroundColor: secondaryColor
11883
- }
11884
- })
11885
- ]
11897
+ children: [/* @__PURE__ */ jsx(BarLabel, { label: entry.label }), bars]
11886
11898
  });
11887
11899
  };
11888
11900
  /**
@@ -11967,6 +11979,26 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
11967
11979
  withComparison,
11968
11980
  withOverlayLabel
11969
11981
  ]);
11982
+ const divergingScale = useMemo(() => {
11983
+ const withComparisonBars = withComparison && !withOverlayLabel;
11984
+ const scale = {
11985
+ negative: 0,
11986
+ positive: 0
11987
+ };
11988
+ for (const entry of data ?? []) {
11989
+ const shares = [entry.currentShare];
11990
+ if (withComparisonBars && hasPreviousValue(entry)) shares.push(entry.previousShare);
11991
+ for (const share of shares) {
11992
+ const side = share < 0 ? "negative" : "positive";
11993
+ scale[side] = Math.max(scale[side], Math.abs(share));
11994
+ }
11995
+ }
11996
+ return scale.negative > 0 ? scale : void 0;
11997
+ }, [
11998
+ data,
11999
+ withComparison,
12000
+ withOverlayLabel
12001
+ ]);
11970
12002
  const isDataValid = Boolean(data && data.length > 0);
11971
12003
  const chartMetadata = useMemo(() => ({
11972
12004
  withComparison,
@@ -11982,6 +12014,8 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
11982
12014
  const prefersReducedMotion = usePrefersReducedMotion();
11983
12015
  const { contentRef, fittedCount, isMeasurable } = useFittedRowCount(fitRows && !allSeriesHidden, data?.length ?? 0, data);
11984
12016
  const shouldFitRows = fitRows && isMeasurable;
12017
+ const showComparisonColumn = withComparison && isComparisonVisible;
12018
+ const templateColumns = showComparisonColumn && isPrimaryVisible ? "minmax(0, 1fr) auto auto" : "minmax(0, 1fr) auto";
11985
12019
  if (!data || data.length === 0) return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
11986
12020
  value: { chartId },
11987
12021
  children: /* @__PURE__ */ jsx(ChartLayout, {
@@ -12046,13 +12080,12 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
12046
12080
  }) : /* @__PURE__ */ jsx(component_default, {
12047
12081
  role: "list",
12048
12082
  "aria-label": ariaLabel ?? __("Leaderboard chart", "jetpack-charts"),
12049
- templateColumns: "minmax(0, 1fr) auto",
12083
+ templateColumns,
12050
12084
  rowGap: ROW_GAP,
12051
12085
  columnGap: COLUMN_GAP,
12052
12086
  "data-leaderboard-grid": true,
12053
12087
  children: data.map((entry, rowIndex) => {
12054
12088
  const rowStyle = shouldFitRows && rowIndex >= fittedCount ? { visibility: "hidden" } : void 0;
12055
- const showComparisonColumn = withComparison && isComparisonVisible;
12056
12089
  const hasPreviousPeriodValue = hasPreviousValue(entry);
12057
12090
  const hasDelta = hasDeltaValue(entry);
12058
12091
  const showComparisonValue = showComparisonColumn && hasDelta;
@@ -12067,13 +12100,12 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
12067
12100
  withOverlayLabel,
12068
12101
  primaryColor: resolvedPrimaryColor,
12069
12102
  secondaryColor: resolvedSecondaryColor,
12103
+ divergingScale,
12070
12104
  isPrimaryVisible,
12071
12105
  isComparisonVisible,
12072
12106
  animation: animation && !loading && !prefersReducedMotion
12073
12107
  })
12074
- }), /* @__PURE__ */ jsxs(Stack, {
12075
- direction: "row",
12076
- gap: "xs",
12108
+ }), /* @__PURE__ */ jsxs("div", {
12077
12109
  className: clsx(leaderboard_chart_module_default.valueContainer, { [leaderboard_chart_module_default.overlayLabel]: withOverlayLabel }),
12078
12110
  children: [
12079
12111
  isPrimaryVisible && /* @__PURE__ */ jsx(Text$1, { children: valueFormatter(entry.currentValue) }),
@@ -12154,8 +12186,7 @@ const LeaderboardChartWithProvider = (props) => {
12154
12186
  LeaderboardChartWithProvider.displayName = "LeaderboardChart";
12155
12187
  const LeaderboardChart = attachSubComponents(LeaderboardChartWithProvider, { Legend });
12156
12188
  const LeaderboardChartResponsive = attachSubComponents(withResponsive(LeaderboardChartWithProvider), { Legend });
12157
- //#endregion
12158
- //#region src/charts/private/pie-keyboard-navigation/order-arcs-for-navigation.ts
12189
+ // src/charts/private/pie-keyboard-navigation/order-arcs-for-navigation.ts
12159
12190
  /**
12160
12191
  * Orders arcs the way they appear: clockwise from 12 o'clock, which for a semi-circle is left to right.
12161
12192
  *
@@ -12163,15 +12194,13 @@ const LeaderboardChartResponsive = attachSubComponents(withResponsive(Leaderboar
12163
12194
  * @return A copy of `arcs` sorted by angular midpoint.
12164
12195
  */
12165
12196
  const orderArcsForNavigation = (arcs) => [...arcs].sort((a, b) => a.startAngle + a.endAngle - (b.startAngle + b.endAngle));
12166
- //#endregion
12167
- //#region src/charts/private/pie-keyboard-navigation/pie-selection-announcement.tsx
12197
+ // src/charts/private/pie-keyboard-navigation/pie-selection-announcement.tsx
12168
12198
  const PieSelectionAnnouncement = ({ data }) => /* @__PURE__ */ jsx(VisuallyHidden, {
12169
12199
  role: "status",
12170
12200
  "aria-atomic": "true",
12171
12201
  children: data && /* @__PURE__ */ jsx(LabelValueContent, { data })
12172
12202
  });
12173
- //#endregion
12174
- //#region src/charts/private/pie-keyboard-navigation/pie-tooltip.tsx
12203
+ // src/charts/private/pie-keyboard-navigation/pie-tooltip.tsx
12175
12204
  const TOOLTIP_BOX_STYLE = { zIndex: 3 };
12176
12205
  const PieTooltip = ({ top, left, selectedIndex, tooltipRef, children }) => {
12177
12206
  const standaloneScopeClass = useStandaloneScopeClass();
@@ -12193,8 +12222,7 @@ const PieTooltip = ({ top, left, selectedIndex, tooltipRef, children }) => {
12193
12222
  }, `chart-tooltip-${selectedIndex}`)
12194
12223
  });
12195
12224
  };
12196
- //#endregion
12197
- //#region src/charts/private/pie-keyboard-navigation/pie-selection-output.tsx
12225
+ // src/charts/private/pie-keyboard-navigation/pie-selection-output.tsx
12198
12226
  /**
12199
12227
  * Reports the selected segment: a focused tooltip for a keyboard selection, a pointer tooltip on hover, or a screen reader announcement without tooltips.
12200
12228
  *
@@ -12234,8 +12262,7 @@ const PieSelectionOutput = ({ withTooltips, selectedIndex, selectedData, keyboar
12234
12262
  })
12235
12263
  ] });
12236
12264
  };
12237
- //#endregion
12238
- //#region src/charts/private/pie-keyboard-navigation/use-pie-keyboard-navigation.ts
12265
+ // src/charts/private/pie-keyboard-navigation/use-pie-keyboard-navigation.ts
12239
12266
  const usePieKeyboardNavigation = ({ navigationArcs, withTooltips, tooltipOffsetX, tooltipOffsetY }) => {
12240
12267
  const chartRef = useRef(null);
12241
12268
  const svgRef = useRef(null);
@@ -12315,8 +12342,7 @@ const usePieKeyboardNavigation = ({ navigationArcs, withTooltips, tooltipOffsetX
12315
12342
  }
12316
12343
  };
12317
12344
  };
12318
- //#endregion
12319
- //#region src/charts/private/radial-wipe-animation/radial-wipe-animation.tsx
12345
+ // src/charts/private/radial-wipe-animation/radial-wipe-animation.tsx
12320
12346
  /**
12321
12347
  * Renders a SVG mask that creates a radial wipe animation effect.
12322
12348
  *
@@ -12353,8 +12379,7 @@ function RadialWipeAnimation({ id, radius, innerRadius = 0, durationMs = 1e3, wi
12353
12379
  })
12354
12380
  });
12355
12381
  }
12356
- //#endregion
12357
- //#region src/charts/pie-chart/pie-chart.module.scss
12382
+ // src/charts/pie-chart/pie-chart.module.scss
12358
12383
  var pie_chart_module_default = {
12359
12384
  "pie-chart": "a8ccharts-gnszbG-pie-chart",
12360
12385
  "pie-chart__label-plate": "a8ccharts-gnszbG-pie-chart__label-plate",
@@ -12365,8 +12390,7 @@ var pie_chart_module_default = {
12365
12390
  "pie-chart__plot": "a8ccharts-gnszbG-pie-chart__plot",
12366
12391
  "pie-chart--responsive": "a8ccharts-gnszbG-pie-chart--responsive"
12367
12392
  };
12368
- //#endregion
12369
- //#region src/charts/pie-chart/pie-chart.tsx
12393
+ // src/charts/pie-chart/pie-chart.tsx
12370
12394
  /**
12371
12395
  * Default tooltip renderer for pie charts.
12372
12396
  * Renders the default `label: value` tooltip content for the hovered segment.
@@ -12649,8 +12673,7 @@ const PieChartResponsive = attachSubComponents(withResponsive(PieChartWithProvid
12649
12673
  SVG: ChartSVG,
12650
12674
  HTML: ChartHTML
12651
12675
  });
12652
- //#endregion
12653
- //#region src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss
12676
+ // src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss
12654
12677
  var pie_semi_circle_chart_module_default = {
12655
12678
  "label": "a8ccharts-YtTOxW-label",
12656
12679
  "note": "a8ccharts-YtTOxW-note",
@@ -12658,8 +12681,7 @@ var pie_semi_circle_chart_module_default = {
12658
12681
  "pie-semi-circle-chart__plot": "a8ccharts-YtTOxW-pie-semi-circle-chart__plot",
12659
12682
  "pie-semi-circle-chart--responsive": "a8ccharts-YtTOxW-pie-semi-circle-chart--responsive"
12660
12683
  };
12661
- //#endregion
12662
- //#region src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx
12684
+ // src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx
12663
12685
  /**
12664
12686
  * Default tooltip renderer for semi-circle pie charts.
12665
12687
  * Renders the default `label: value` tooltip content for the hovered segment.
@@ -12902,14 +12924,12 @@ const PieSemiCircleChartResponsive = attachSubComponents(withResponsive(PieSemiC
12902
12924
  SVG: ChartSVG,
12903
12925
  HTML: ChartHTML
12904
12926
  });
12905
- //#endregion
12906
- //#region src/charts/sparkline/sparkline.module.scss
12927
+ // src/charts/sparkline/sparkline.module.scss
12907
12928
  var sparkline_module_default = {
12908
12929
  "sparkline": "a8ccharts-GtgAVa-sparkline",
12909
12930
  "sparkline--empty": "a8ccharts-GtgAVa-sparkline--empty"
12910
12931
  };
12911
- //#endregion
12912
- //#region src/charts/sparkline/sparkline.tsx
12932
+ // src/charts/sparkline/sparkline.tsx
12913
12933
  const DEFAULT_WIDTH = 100;
12914
12934
  const DEFAULT_HEIGHT = 40;
12915
12935
  /**
@@ -13051,8 +13071,7 @@ SparklineUnresponsive.displayName = "SparklineUnresponsive";
13051
13071
  * Responsive Sparkline chart component
13052
13072
  */
13053
13073
  const Sparkline = withResponsive(SparklineUnresponsive);
13054
- //#endregion
13055
- //#region src/components/trend-indicator/trend-indicator.module.scss
13074
+ // src/components/trend-indicator/trend-indicator.module.scss
13056
13075
  var trend_indicator_module_default = {
13057
13076
  "trend-indicator": "a8ccharts-zR7F7G-trend-indicator",
13058
13077
  "trend-indicator__icon": "a8ccharts-zR7F7G-trend-indicator__icon",
@@ -13061,8 +13080,7 @@ var trend_indicator_module_default = {
13061
13080
  "trend-indicator--neutral": "a8ccharts-zR7F7G-trend-indicator--neutral",
13062
13081
  "trend-indicator--up": "a8ccharts-zR7F7G-trend-indicator--up"
13063
13082
  };
13064
- //#endregion
13065
- //#region src/components/trend-indicator/trend-indicator.tsx
13083
+ // src/components/trend-indicator/trend-indicator.tsx
13066
13084
  const DIRECTION_LABELS = {
13067
13085
  up: "Increase",
13068
13086
  down: "Decrease",
@@ -13105,7 +13123,6 @@ function TrendIndicator({ direction, value, className, style, showIcon = true })
13105
13123
  })]
13106
13124
  });
13107
13125
  }
13108
- //#endregion
13109
13126
  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, useBarColors, useBarLegendItems, useCalendarHeatmapData, useChartFormatting, useChartLegendItems, useChartRegistration, useChartScopeElement, useGlobalChartsContext, useGlobalChartsTheme, useLeaderboardLegendItems, useMonthCalendarHeatmapData, validateHexColor };
13110
13127
 
13111
13128
  //# sourceMappingURL=index.js.map