@automattic/charts 4.3.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.4.0] - 2026-09-23
9
+ ### Added
10
+ - Bar chart: Add per-datum bar classes and tooltip box style overrides. [#52547]
11
+
12
+ ### Fixed
13
+ - Bar chart: Fix the comparison shadow baseline on horizontal charts whose domain excludes zero. [#52547]
14
+
8
15
  ## [4.3.0] - 2026-09-23
9
16
  ### Added
10
17
  - Add required key and index fields to BandHighlightSelection for identifying the selected series and rendered data point. [#52544]
@@ -1108,6 +1115,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1108
1115
  - Fixed lints following ESLint rule changes for TS [#40584]
1109
1116
  - Fixing a bug in Chart storybook data. [#40640]
1110
1117
 
1118
+ [4.4.0]: https://github.com/Automattic/charts/compare/v4.3.0...v4.4.0
1111
1119
  [4.3.0]: https://github.com/Automattic/charts/compare/v4.2.0...v4.3.0
1112
1120
  [4.2.0]: https://github.com/Automattic/charts/compare/v4.1.1...v4.2.0
1113
1121
  [4.1.1]: https://github.com/Automattic/charts/compare/v4.1.0...v4.1.1
package/dist/index.cjs CHANGED
@@ -5661,9 +5661,8 @@ const createGroupScale = (keys, bandwidth, padding) => (0, _visx_scale.scaleBand
5661
5661
  //#endregion
5662
5662
  //#region src/charts/bar-chart/private/comparison-bars-geometry.ts
5663
5663
  /**
5664
- * Output position of a value scale's baseline: zero if in-domain, else the
5665
- * nearest range edge. Mirrors visx's getScaleBaseline so comparison shadows
5666
- * sit on the same baseline as primary bars.
5664
+ * Mirrors visx's getScaleBaseline so comparison shadows and primary bars
5665
+ * share the same baseline, including out-of-domain zero values.
5667
5666
  *
5668
5667
  * @param {ValueScale} scale - The continuous value scale.
5669
5668
  * @return {number} The baseline output position in pixels.
@@ -5674,7 +5673,7 @@ function getValueScaleBaseline(scale) {
5674
5673
  const maybeZero = scale(0);
5675
5674
  const [minOutput, maxOutput] = isDescending ? [b, a] : [a, b];
5676
5675
  if (isDescending) return Number.isFinite(maybeZero) ? Math.min(Math.max(minOutput, maybeZero), maxOutput) : maxOutput;
5677
- return Number.isFinite(maybeZero) ? Math.min(Math.max(maybeZero, minOutput), maxOutput) : minOutput;
5676
+ return Number.isFinite(maybeZero) ? Math.max(maybeZero, minOutput) : minOutput;
5678
5677
  }
5679
5678
  /**
5680
5679
  * Compute the rect for a comparison "shadow" bar, centered on the paired
@@ -5710,6 +5709,51 @@ function computeComparisonRect(params) {
5710
5709
  height: valueLength
5711
5710
  };
5712
5711
  }
5712
+ //#endregion
5713
+ //#region src/charts/bar-chart/private/classified-bar-series.tsx
5714
+ const ClassifiedBarSeries = ({ barClassName, primaryKeys, groupPadding, ...props }) => {
5715
+ const { xScale, yScale, horizontal } = (0, react.useContext)(_visx_xychart.DataContext);
5716
+ const bandScale = horizontal ? yScale : xScale;
5717
+ const valueScale = horizontal ? xScale : yScale;
5718
+ const groupScale = (0, react.useMemo)(() => createGroupScale(primaryKeys, bandScale?.bandwidth?.() ?? 0, groupPadding), [
5719
+ primaryKeys,
5720
+ bandScale,
5721
+ groupPadding
5722
+ ]);
5723
+ const renderGlyph = (0, react.useCallback)(({ datum, x, y, color, onBlur, onFocus, onPointerMove, onPointerOut, onPointerUp }) => {
5724
+ if (!bandScale?.bandwidth || !valueScale) return null;
5725
+ const baseline = getValueScaleBaseline(valueScale);
5726
+ const position = Number(bandScale((horizontal ? props.yAccessor : props.xAccessor)(datum))) + (groupScale(props.dataKey) ?? 0);
5727
+ const value = horizontal ? x : y;
5728
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
5729
+ className: (0, clsx.default)("visx-bar", barClassName(datum)),
5730
+ tabIndex: onFocus || onBlur ? 0 : void 0,
5731
+ onBlur,
5732
+ onFocus,
5733
+ onPointerMove,
5734
+ onPointerOut,
5735
+ onPointerUp,
5736
+ x: horizontal ? baseline + Math.min(0, value - baseline) : position,
5737
+ y: horizontal ? position : baseline + Math.min(0, value - baseline),
5738
+ width: horizontal ? Math.abs(value - baseline) : groupScale.bandwidth(),
5739
+ height: horizontal ? groupScale.bandwidth() : Math.abs(value - baseline),
5740
+ fill: color
5741
+ });
5742
+ }, [
5743
+ bandScale,
5744
+ valueScale,
5745
+ horizontal,
5746
+ groupScale,
5747
+ props.dataKey,
5748
+ props.xAccessor,
5749
+ props.yAccessor,
5750
+ barClassName
5751
+ ]);
5752
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.GlyphSeries, {
5753
+ ...props,
5754
+ renderGlyph
5755
+ });
5756
+ };
5713
5757
  /**
5714
5758
  * Upper clamp on the computed group padding, so bars can never collapse to zero width
5715
5759
  * even at very large `widthFactor` values.
@@ -5953,7 +5997,7 @@ const renderTooltipRow = (label, value) => /* @__PURE__ */ (0, react_jsx_runtime
5953
5997
  className: bar_chart_module_default["bar-chart__tooltip-row"],
5954
5998
  children: (0, _wordpress_i18n.sprintf)((0, _wordpress_i18n.__)("%1$s: %2$s", "jetpack-charts"), label, value)
5955
5999
  });
5956
- const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, tooltipPlacement, tooltipAnchorTop, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, withBandHighlight = false, onBandHighlightChange, defaultHiddenSeries, animation, children, gap = "md", onPointerDown, onPointerUp, onDatumActivate }) => {
6000
+ const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, tooltipPlacement, tooltipAnchorTop, tooltipStyle, barClassName, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, withBandHighlight = false, onBandHighlightChange, defaultHiddenSeries, animation, children, gap = "md", onPointerDown, onPointerUp, onDatumActivate }) => {
5957
6001
  if (!withTooltips && (withBandHighlight || onBandHighlightChange)) warnOnce("bar-chart-band-highlight-without-tooltips", "BarChart: withBandHighlight and onBandHighlightChange require withTooltips.");
5958
6002
  const legendInteractive = legend.interactive ?? false;
5959
6003
  const legendCollapseGroups = legend.collapseGroups ?? false;
@@ -6323,7 +6367,19 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
6323
6367
  getElementStyles,
6324
6368
  resolveFill: resolveComparisonFill
6325
6369
  }),
6326
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.BarGroup, {
6370
+ barClassName ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("g", {
6371
+ className: "visx-bar-group",
6372
+ children: primaryEntries.map(({ series: seriesData, index }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClassifiedBarSeries, {
6373
+ dataKey: seriesData.label,
6374
+ data: seriesData.data,
6375
+ xAccessor: chartOptions.accessors.xAccessor,
6376
+ yAccessor: chartOptions.accessors.yAccessor,
6377
+ colorAccessor: getBarBackground(index),
6378
+ barClassName,
6379
+ primaryKeys,
6380
+ groupPadding
6381
+ }, seriesData.label))
6382
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.BarGroup, {
6327
6383
  padding: groupPadding,
6328
6384
  children: primaryEntries.map(({ series: seriesData, index }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.BarSeries, {
6329
6385
  dataKey: seriesData?.label,
@@ -6353,6 +6409,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
6353
6409
  withTooltips && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccessibleTooltip, {
6354
6410
  tooltipPlacement,
6355
6411
  tooltipAnchorTop,
6412
+ style: tooltipStyle,
6356
6413
  detectBounds: true,
6357
6414
  snapTooltipToDatumX: true,
6358
6415
  snapTooltipToDatumY: true,