@automattic/charts 1.7.0 → 1.8.1
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 +13 -0
- package/dist/index.cjs +347 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +6 -4
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +348 -62
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/charts/bar-chart/bar-chart.tsx +210 -49
- package/src/charts/bar-chart/private/comparison-bars-geometry.ts +70 -0
- package/src/charts/bar-chart/private/comparison-bars.tsx +155 -0
- package/src/charts/bar-chart/private/comparison-constants.ts +33 -0
- package/src/charts/bar-chart/private/index.ts +9 -0
- package/src/charts/bar-chart/private/test/comparison-bars-geometry.test.ts +47 -0
- package/src/charts/bar-chart/private/test/comparison-bars.test.tsx +183 -0
- package/src/charts/bar-chart/private/use-bar-chart-options.ts +49 -5
- package/src/charts/bar-chart/test/bar-chart.test.tsx +329 -1
- package/src/charts/geo-chart/geo-chart.tsx +5 -9
- package/src/charts/pie-chart/pie-chart.module.scss +0 -4
- package/src/charts/pie-chart/pie-chart.tsx +3 -8
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss +0 -5
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +3 -8
- package/src/charts/private/center/center.module.scss +4 -0
- package/src/charts/private/center/center.tsx +33 -0
- package/src/charts/private/center/index.ts +2 -0
- package/src/charts/private/center/test/center.test.tsx +60 -0
- package/src/charts/private/svg-empty-state/svg-empty-state.module.scss +0 -2
- package/src/charts/private/svg-empty-state/svg-empty-state.tsx +2 -4
- package/src/providers/chart-context/global-charts-provider.tsx +2 -0
- package/src/providers/chart-context/test/chart-context.test.tsx +13 -1
- package/src/providers/chart-context/themes.ts +8 -0
- package/src/providers/chart-context/types.ts +2 -0
- package/src/types.ts +16 -0
- package/src/utils/get-styles.ts +36 -13
- package/src/utils/index.ts +6 -1
- package/src/utils/test/get-styles.test.ts +47 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ 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
|
+
## [1.8.1] - 2026-06-26
|
|
9
|
+
### Fixed
|
|
10
|
+
- Fix Bar Chart comparison mode — pair the keyboard tooltip with the focused bar, keep the value axis zero-based, and make the tooltip label/value separator translatable. [#49959]
|
|
11
|
+
|
|
12
|
+
## [1.8.0] - 2026-06-24
|
|
13
|
+
### Added
|
|
14
|
+
- Add comparison mode to the Bar Chart — a translucent shadow bar (standard slot width, 50% opacity) rendered behind each primary bar, paired by group. Primary bars are narrowed to 1/widthFactor of the slot (default widthFactor 1.5 → ~67% width, centered), with widthFactor as the single control. [#49676]
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Add an internal Center layout primitive and use it for centered chart wrappers. [#49164]
|
|
18
|
+
|
|
8
19
|
## [1.7.0] - 2026-06-23
|
|
9
20
|
### Added
|
|
10
21
|
- Leaderboard interactive rows gain an opt-in `ariaLabel` for image-only labels, and the hover affordance now shrinks each bar in proportion to its length so small-share rows stay consistent. [#49812]
|
|
@@ -878,6 +889,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
878
889
|
- Fixed lints following ESLint rule changes for TS [#40584]
|
|
879
890
|
- Fixing a bug in Chart storybook data. [#40640]
|
|
880
891
|
|
|
892
|
+
[1.8.1]: https://github.com/Automattic/charts/compare/v1.8.0...v1.8.1
|
|
893
|
+
[1.8.0]: https://github.com/Automattic/charts/compare/v1.7.0...v1.8.0
|
|
881
894
|
[1.7.0]: https://github.com/Automattic/charts/compare/v1.6.0...v1.7.0
|
|
882
895
|
[1.6.0]: https://github.com/Automattic/charts/compare/v1.5.3...v1.6.0
|
|
883
896
|
[1.5.3]: https://github.com/Automattic/charts/compare/v1.5.2...v1.5.3
|
package/dist/index.cjs
CHANGED
|
@@ -266,6 +266,20 @@ function getSeriesLineStyles(seriesData, index, providerTheme) {
|
|
|
266
266
|
return seriesData.options?.seriesLineStyle ?? themeSemanticLineStyle ?? themeSeriesLineStyle ?? {};
|
|
267
267
|
}
|
|
268
268
|
/**
|
|
269
|
+
* Utility to get consolidated bar styles for a series by semantic type.
|
|
270
|
+
* Mirrors getSeriesLineStyles: a series with `options.type` (e.g. 'comparison')
|
|
271
|
+
* resolves to `theme.barChart.barStyles[ type ]`.
|
|
272
|
+
*
|
|
273
|
+
* @param {SeriesData} seriesData - The series data containing styling options
|
|
274
|
+
* @param {number} index - The index of the series in the data array
|
|
275
|
+
* @param {ChartTheme} providerTheme - The chart theme configuration
|
|
276
|
+
* @return {BarStyles} The consolidated bar styles for the series
|
|
277
|
+
*/
|
|
278
|
+
function getSeriesBarStyles(seriesData, index, providerTheme) {
|
|
279
|
+
const type = seriesData.options?.type;
|
|
280
|
+
return (type && providerTheme?.barChart?.barStyles?.[type]) ?? {};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
269
283
|
* Utility function to get shape styles for a legend item
|
|
270
284
|
*
|
|
271
285
|
* @param {SeriesData} series - The series data containing styling options
|
|
@@ -277,13 +291,17 @@ function getSeriesLineStyles(seriesData, index, providerTheme) {
|
|
|
277
291
|
function getItemShapeStyles(series, index, theme, legendShape) {
|
|
278
292
|
const seriesShapeStyles = series.options?.legendShapeStyle ?? {};
|
|
279
293
|
const lineStyles = legendShape === "line" ? getSeriesLineStyles(series, index, theme) : {};
|
|
294
|
+
const barOpacity = legendShape !== "line" ? getSeriesBarStyles(series, index, theme).opacity : void 0;
|
|
295
|
+
const barShapeStyles = barOpacity !== void 0 ? { opacity: barOpacity } : {};
|
|
280
296
|
const themeShapeStyles = theme.legend?.shapeStyles?.[index];
|
|
281
|
-
const
|
|
297
|
+
const explicitStyles = {
|
|
282
298
|
...seriesShapeStyles,
|
|
283
299
|
...lineStyles
|
|
284
300
|
};
|
|
285
|
-
|
|
286
|
-
|
|
301
|
+
return {
|
|
302
|
+
...Object.values(explicitStyles).some((value) => value !== void 0 && value !== null && value !== "") ? explicitStyles : themeShapeStyles ?? {},
|
|
303
|
+
...barShapeStyles
|
|
304
|
+
};
|
|
287
305
|
}
|
|
288
306
|
//#endregion
|
|
289
307
|
//#region src/utils/is-safari.ts
|
|
@@ -729,6 +747,10 @@ const defaultTheme = {
|
|
|
729
747
|
strokeDasharray: "4 4",
|
|
730
748
|
strokeLinecap: "square"
|
|
731
749
|
} } },
|
|
750
|
+
barChart: { barStyles: { comparison: {
|
|
751
|
+
widthFactor: 1.5,
|
|
752
|
+
opacity: .5
|
|
753
|
+
} } },
|
|
732
754
|
sparkline: {
|
|
733
755
|
margin: {
|
|
734
756
|
top: 2,
|
|
@@ -835,6 +857,7 @@ const GlobalChartsProvider = ({ children, theme }) => {
|
|
|
835
857
|
overrideColor: overrideColor || isSeriesData && data?.options?.stroke || isPointPercentageData && data?.color
|
|
836
858
|
}),
|
|
837
859
|
lineStyles: isSeriesData ? getSeriesLineStyles(data, index, providerTheme) : {},
|
|
860
|
+
barStyles: isSeriesData ? getSeriesBarStyles(data, index, providerTheme) : {},
|
|
838
861
|
glyph: providerTheme.glyphs?.[index],
|
|
839
862
|
shapeStyles: isSeriesData ? getItemShapeStyles(data, index, providerTheme, legendShape) : {}
|
|
840
863
|
};
|
|
@@ -2639,6 +2662,32 @@ const DefaultGlyph = (props) => {
|
|
|
2639
2662
|
});
|
|
2640
2663
|
};
|
|
2641
2664
|
//#endregion
|
|
2665
|
+
//#region src/charts/private/center/center.module.scss
|
|
2666
|
+
var center_module_default = { "center": "a8ccharts-w3qxlG-center" };
|
|
2667
|
+
//#endregion
|
|
2668
|
+
//#region src/charts/private/center/center.tsx
|
|
2669
|
+
/**
|
|
2670
|
+
* Centers its children on both axes and fills its parent.
|
|
2671
|
+
*
|
|
2672
|
+
* A thin wrapper around `Stack` with `align="center"` and `justify="center"`
|
|
2673
|
+
* defaults (both overridable) plus `width: 100%; height: 100%`. Reads more
|
|
2674
|
+
* honestly than a `Stack` with both axes centered, and lets call sites drop
|
|
2675
|
+
* ad-hoc `*__centering` classes. Forwards its ref and spreads remaining props
|
|
2676
|
+
* onto the underlying `Stack`.
|
|
2677
|
+
*
|
|
2678
|
+
* @param props - Stack props; `align`/`justify` default to `"center"`.
|
|
2679
|
+
* @param ref - Forwarded to the underlying element.
|
|
2680
|
+
* @return The centered layout element.
|
|
2681
|
+
*/
|
|
2682
|
+
const Center = (0, react$1.forwardRef)(({ align = "center", justify = "center", className, ...props }, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Stack, {
|
|
2683
|
+
ref,
|
|
2684
|
+
align,
|
|
2685
|
+
justify,
|
|
2686
|
+
className: (0, clsx.default)(center_module_default.center, className),
|
|
2687
|
+
...props
|
|
2688
|
+
}));
|
|
2689
|
+
Center.displayName = "Center";
|
|
2690
|
+
//#endregion
|
|
2642
2691
|
//#region src/charts/private/svg-empty-state/svg-empty-state.module.scss
|
|
2643
2692
|
var svg_empty_state_module_default = { "svg-empty-state": "a8ccharts-udGPVq-svg-empty-state" };
|
|
2644
2693
|
//#endregion
|
|
@@ -2663,9 +2712,7 @@ const SvgEmptyState = ({ x, y, width, height, children }) => {
|
|
|
2663
2712
|
y: y - height / 2,
|
|
2664
2713
|
width,
|
|
2665
2714
|
height,
|
|
2666
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2667
|
-
align: "center",
|
|
2668
|
-
justify: "center",
|
|
2715
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Center, {
|
|
2669
2716
|
className: svg_empty_state_module_default["svg-empty-state"],
|
|
2670
2717
|
children
|
|
2671
2718
|
})
|
|
@@ -4345,6 +4392,10 @@ const TruncatedXTickComponent = createTruncatedTickComponent("x");
|
|
|
4345
4392
|
const TruncatedYTickComponent = createTruncatedTickComponent("y");
|
|
4346
4393
|
//#endregion
|
|
4347
4394
|
//#region src/charts/bar-chart/private/use-bar-chart-options.ts
|
|
4395
|
+
/** Outer padding of the category band scale (space at the chart edges). */
|
|
4396
|
+
const BASE_BAND_PADDING = .2;
|
|
4397
|
+
/** Inner padding of the category band scale (the base gap between ticks). */
|
|
4398
|
+
const BASE_BAND_PADDING_INNER = .1;
|
|
4348
4399
|
const formatDateTick = (timestamp) => {
|
|
4349
4400
|
return new Date(timestamp).toLocaleDateString(void 0, {
|
|
4350
4401
|
month: "short",
|
|
@@ -4372,8 +4423,8 @@ function useBarChartOptions(data, horizontal, options = {}) {
|
|
|
4372
4423
|
const defaultOptions = (0, react$1.useMemo)(() => {
|
|
4373
4424
|
const bandScale = {
|
|
4374
4425
|
type: "band",
|
|
4375
|
-
padding:
|
|
4376
|
-
paddingInner:
|
|
4426
|
+
padding: BASE_BAND_PADDING,
|
|
4427
|
+
paddingInner: BASE_BAND_PADDING_INNER
|
|
4377
4428
|
};
|
|
4378
4429
|
const linearScale = {
|
|
4379
4430
|
type: "linear",
|
|
@@ -4412,13 +4463,29 @@ function useBarChartOptions(data, horizontal, options = {}) {
|
|
|
4412
4463
|
}, [data]);
|
|
4413
4464
|
return (0, react$1.useMemo)(() => {
|
|
4414
4465
|
const { xTickFormat, yTickFormat, tooltipLabelFormatter: defaultTooltipLabelFormatter, xAccessor, yAccessor, gridVisibility, xScale: baseXScale, yScale: baseYScale } = defaultOptions[horizontal ? "horizontal" : "vertical"];
|
|
4466
|
+
let valueScaleDomainOverride = {};
|
|
4467
|
+
if (data.some((s) => s.options?.type === "comparison")) {
|
|
4468
|
+
if (!(!horizontal ? options.yScale?.domain : options.xScale?.domain)) {
|
|
4469
|
+
const allValues = [];
|
|
4470
|
+
data.forEach((series) => {
|
|
4471
|
+
series.data.forEach((d) => {
|
|
4472
|
+
const enhanced = d;
|
|
4473
|
+
const v = enhanced.visualValue !== void 0 ? enhanced.visualValue : d.value;
|
|
4474
|
+
if (typeof v === "number" && Number.isFinite(v)) allValues.push(v);
|
|
4475
|
+
});
|
|
4476
|
+
});
|
|
4477
|
+
if (allValues.length > 0) valueScaleDomainOverride = { domain: [Math.min(0, ...allValues), Math.max(0, ...allValues)] };
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4415
4480
|
const xScale = {
|
|
4416
4481
|
...baseXScale,
|
|
4417
|
-
...options.xScale || {}
|
|
4482
|
+
...options.xScale || {},
|
|
4483
|
+
...horizontal ? valueScaleDomainOverride : {}
|
|
4418
4484
|
};
|
|
4419
4485
|
const yScale = {
|
|
4420
4486
|
...baseYScale,
|
|
4421
|
-
...options.yScale || {}
|
|
4487
|
+
...options.yScale || {},
|
|
4488
|
+
...!horizontal ? valueScaleDomainOverride : {}
|
|
4422
4489
|
};
|
|
4423
4490
|
const providedToolTipLabelFormatter = horizontal ? options.axis?.y?.tickFormat : options.axis?.x?.tickFormat;
|
|
4424
4491
|
const { labelOverflow: xLabelOverflow, ...xAxisOptions } = options.axis?.x || {};
|
|
@@ -4453,10 +4520,144 @@ function useBarChartOptions(data, horizontal, options = {}) {
|
|
|
4453
4520
|
}, [
|
|
4454
4521
|
defaultOptions,
|
|
4455
4522
|
options,
|
|
4456
|
-
horizontal
|
|
4523
|
+
horizontal,
|
|
4524
|
+
data
|
|
4457
4525
|
]);
|
|
4458
4526
|
}
|
|
4459
4527
|
//#endregion
|
|
4528
|
+
//#region src/charts/bar-chart/private/comparison-bars-geometry.ts
|
|
4529
|
+
/**
|
|
4530
|
+
* Output position of a value scale's baseline: zero if in-domain, else the
|
|
4531
|
+
* nearest range edge. Mirrors visx's getScaleBaseline so comparison shadows
|
|
4532
|
+
* sit on the same baseline as primary bars.
|
|
4533
|
+
*
|
|
4534
|
+
* @param {ValueScale} scale - The continuous value scale.
|
|
4535
|
+
* @return {number} The baseline output position in pixels.
|
|
4536
|
+
*/
|
|
4537
|
+
function getValueScaleBaseline(scale) {
|
|
4538
|
+
const [a, b] = scale.range().map((r) => Number(r) || 0);
|
|
4539
|
+
const isDescending = b < a;
|
|
4540
|
+
const maybeZero = scale(0);
|
|
4541
|
+
const [minOutput, maxOutput] = isDescending ? [b, a] : [a, b];
|
|
4542
|
+
if (isDescending) return Number.isFinite(maybeZero) ? Math.min(Math.max(minOutput, maybeZero), maxOutput) : maxOutput;
|
|
4543
|
+
return Number.isFinite(maybeZero) ? Math.min(Math.max(maybeZero, minOutput), maxOutput) : minOutput;
|
|
4544
|
+
}
|
|
4545
|
+
/**
|
|
4546
|
+
* Compute the rect for a comparison "shadow" bar, centered on the paired
|
|
4547
|
+
* primary bar slot and scaled by `widthFactor`.
|
|
4548
|
+
*
|
|
4549
|
+
* @param {object} params - Geometry inputs.
|
|
4550
|
+
* @param {boolean} params.horizontal - True for a horizontal bar chart, false for vertical.
|
|
4551
|
+
* @param {number} params.bandPosition - bandScale(category): start px of the category band.
|
|
4552
|
+
* @param {number} params.slotOffset - groupScale(primaryKey): offset of the primary slot within the band.
|
|
4553
|
+
* @param {number} params.slotThickness - groupScale.bandwidth(): primary bar thickness in px.
|
|
4554
|
+
* @param {number} params.valuePosition - valueScale(value): output px for the bar's data value.
|
|
4555
|
+
* @param {number} params.baseline - getValueScaleBaseline(valueScale): zero-line output px.
|
|
4556
|
+
* @param {number} params.widthFactor - Shadow thickness multiplier, e.g. 1.5 for 150% width.
|
|
4557
|
+
* @return {ComparisonRect} The {x, y, width, height} of the shadow rect.
|
|
4558
|
+
*/
|
|
4559
|
+
function computeComparisonRect(params) {
|
|
4560
|
+
const { horizontal, bandPosition, slotOffset, slotThickness, valuePosition, baseline, widthFactor } = params;
|
|
4561
|
+
const slotStart = bandPosition + slotOffset;
|
|
4562
|
+
const shadowThickness = slotThickness * widthFactor;
|
|
4563
|
+
const shadowStart = slotStart + slotThickness / 2 - shadowThickness / 2;
|
|
4564
|
+
const valueStart = Math.min(valuePosition, baseline);
|
|
4565
|
+
const valueLength = Math.abs(baseline - valuePosition);
|
|
4566
|
+
if (horizontal) return {
|
|
4567
|
+
x: valueStart,
|
|
4568
|
+
y: shadowStart,
|
|
4569
|
+
width: valueLength,
|
|
4570
|
+
height: shadowThickness
|
|
4571
|
+
};
|
|
4572
|
+
return {
|
|
4573
|
+
x: shadowStart,
|
|
4574
|
+
y: valueStart,
|
|
4575
|
+
width: shadowThickness,
|
|
4576
|
+
height: valueLength
|
|
4577
|
+
};
|
|
4578
|
+
}
|
|
4579
|
+
/**
|
|
4580
|
+
* Fraction of each per-series step left as a gap between bars within a single tick.
|
|
4581
|
+
* Larger = more space between adjacent series; the shadow spans `1 - COMPARISON_INNER_GAP` of the step.
|
|
4582
|
+
*/
|
|
4583
|
+
const COMPARISON_INNER_GAP = .1;
|
|
4584
|
+
/**
|
|
4585
|
+
* Upper clamp on the computed group padding, so bars can never collapse to zero width
|
|
4586
|
+
* even at very large `widthFactor` values.
|
|
4587
|
+
*/
|
|
4588
|
+
const MAX_GROUP_PADDING = .9;
|
|
4589
|
+
/**
|
|
4590
|
+
* Factor applied to the category band's `paddingInner` in comparison mode to tighten the
|
|
4591
|
+
* gap between ticks. `0.75` = a 25% reduction of the tick-gap padding.
|
|
4592
|
+
*/
|
|
4593
|
+
const COMPARISON_TICK_GAP_FACTOR = .75;
|
|
4594
|
+
//#endregion
|
|
4595
|
+
//#region src/charts/bar-chart/private/comparison-bars.tsx
|
|
4596
|
+
const ComparisonBars = ({ comparisonEntries, primaryKeys, groupPadding, horizontal, xAccessor, yAccessor, getElementStyles, resolveFill }) => {
|
|
4597
|
+
const context = (0, react$1.useContext)(_visx_xychart.DataContext);
|
|
4598
|
+
const xScale = context?.xScale;
|
|
4599
|
+
const yScale = context?.yScale;
|
|
4600
|
+
if (!xScale || !yScale || primaryKeys.length === 0) return null;
|
|
4601
|
+
const bandScale = horizontal ? yScale : xScale;
|
|
4602
|
+
const valueScale = horizontal ? xScale : yScale;
|
|
4603
|
+
const bandwidth = bandScale.bandwidth ? bandScale.bandwidth() : 0;
|
|
4604
|
+
if (!bandwidth) return null;
|
|
4605
|
+
const groupScale = (0, _visx_scale.scaleBand)({
|
|
4606
|
+
domain: primaryKeys,
|
|
4607
|
+
range: [0, bandwidth],
|
|
4608
|
+
padding: groupPadding
|
|
4609
|
+
});
|
|
4610
|
+
const slotThickness = groupScale.bandwidth();
|
|
4611
|
+
const baseline = getValueScaleBaseline(valueScale);
|
|
4612
|
+
const bandAccessor = horizontal ? yAccessor : xAccessor;
|
|
4613
|
+
const valueAccessor = horizontal ? xAccessor : yAccessor;
|
|
4614
|
+
const rects = [];
|
|
4615
|
+
comparisonEntries.forEach((entry) => {
|
|
4616
|
+
const { series, index, primaryKey } = entry;
|
|
4617
|
+
const slotOffset = groupScale(primaryKey);
|
|
4618
|
+
if (slotOffset == null || !Number.isFinite(slotOffset)) return;
|
|
4619
|
+
const { barStyles } = getElementStyles({
|
|
4620
|
+
data: series,
|
|
4621
|
+
index
|
|
4622
|
+
});
|
|
4623
|
+
const opacity = barStyles?.opacity ?? .5;
|
|
4624
|
+
const widthFactor = barStyles?.widthFactor ?? 1.5;
|
|
4625
|
+
const fill = resolveFill(entry);
|
|
4626
|
+
series.data.forEach((datum, i) => {
|
|
4627
|
+
const bandPosition = Number(bandScale(bandAccessor(datum)));
|
|
4628
|
+
const valuePosition = Number(valueScale(Number(valueAccessor(datum))));
|
|
4629
|
+
if (!Number.isFinite(bandPosition) || !Number.isFinite(valuePosition)) {
|
|
4630
|
+
if (process.env.NODE_ENV !== "production" && !Number.isFinite(bandPosition)) console.warn(`[Charts] ComparisonBars: datum key "${String(bandAccessor(datum))}" did not match any primary category. Shadow will not be rendered. Ensure comparison series data uses the same label/date keys as the primary series.`);
|
|
4631
|
+
return;
|
|
4632
|
+
}
|
|
4633
|
+
const rect = computeComparisonRect({
|
|
4634
|
+
horizontal,
|
|
4635
|
+
bandPosition,
|
|
4636
|
+
slotOffset,
|
|
4637
|
+
slotThickness,
|
|
4638
|
+
valuePosition,
|
|
4639
|
+
baseline,
|
|
4640
|
+
widthFactor
|
|
4641
|
+
});
|
|
4642
|
+
rects.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
4643
|
+
x: rect.x,
|
|
4644
|
+
y: rect.y,
|
|
4645
|
+
width: rect.width,
|
|
4646
|
+
height: rect.height,
|
|
4647
|
+
fill,
|
|
4648
|
+
opacity
|
|
4649
|
+
}, `${index}-${i}`));
|
|
4650
|
+
});
|
|
4651
|
+
});
|
|
4652
|
+
if (rects.length === 0) return null;
|
|
4653
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("g", {
|
|
4654
|
+
className: "bar-chart__comparison-bars",
|
|
4655
|
+
pointerEvents: "none",
|
|
4656
|
+
"aria-hidden": "true",
|
|
4657
|
+
children: rects
|
|
4658
|
+
});
|
|
4659
|
+
};
|
|
4660
|
+
//#endregion
|
|
4460
4661
|
//#region src/charts/bar-chart/bar-chart.tsx
|
|
4461
4662
|
const validateData$2 = (data) => {
|
|
4462
4663
|
if (!data?.length) return "No data available";
|
|
@@ -4464,6 +4665,10 @@ const validateData$2 = (data) => {
|
|
|
4464
4665
|
return null;
|
|
4465
4666
|
};
|
|
4466
4667
|
const getPatternId = (chartId, index) => `bar-pattern-${chartId}-${index}`;
|
|
4668
|
+
const renderTooltipRow = (label, value) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4669
|
+
className: bar_chart_module_default["bar-chart__tooltip-row"],
|
|
4670
|
+
children: (0, _wordpress_i18n.sprintf)((0, _wordpress_i18n.__)("%1$s: %2$s", "jetpack-charts"), label, value)
|
|
4671
|
+
});
|
|
4467
4672
|
const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, animation, children, gap = "md" }) => {
|
|
4468
4673
|
const legendInteractive = legend.interactive ?? false;
|
|
4469
4674
|
const horizontal = orientation === "horizontal";
|
|
@@ -4485,13 +4690,14 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4485
4690
|
}, [height]);
|
|
4486
4691
|
const [selectedIndex, setSelectedIndex] = (0, react$1.useState)(void 0);
|
|
4487
4692
|
const [isNavigating, setIsNavigating] = (0, react$1.useState)(false);
|
|
4693
|
+
const primarySeriesForNav = dataWithVisibleZeros.filter((s) => s.options?.type !== "comparison");
|
|
4488
4694
|
const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
|
|
4489
4695
|
selectedIndex,
|
|
4490
4696
|
setSelectedIndex,
|
|
4491
4697
|
isNavigating,
|
|
4492
4698
|
setIsNavigating,
|
|
4493
4699
|
chartRef,
|
|
4494
|
-
totalPoints: Math.max(0, ...
|
|
4700
|
+
totalPoints: Math.max(0, ...primarySeriesForNav.map((s) => s.data?.length || 0)) * primarySeriesForNav.length
|
|
4495
4701
|
});
|
|
4496
4702
|
const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
|
|
4497
4703
|
const seriesWithVisibility = (0, react$1.useMemo)(() => {
|
|
@@ -4514,6 +4720,70 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4514
4720
|
const allSeriesHidden = (0, react$1.useMemo)(() => {
|
|
4515
4721
|
return seriesWithVisibility.every(({ isVisible }) => !isVisible);
|
|
4516
4722
|
}, [seriesWithVisibility]);
|
|
4723
|
+
const primaryEntries = (0, react$1.useMemo)(() => seriesWithVisibility.filter(({ isVisible, series }) => isVisible && series.options?.type !== "comparison"), [seriesWithVisibility]);
|
|
4724
|
+
const primaryKeys = (0, react$1.useMemo)(() => primaryEntries.map(({ series }) => series.label), [primaryEntries]);
|
|
4725
|
+
const primarySeries = (0, react$1.useMemo)(() => primaryEntries.map(({ series }) => series), [primaryEntries]);
|
|
4726
|
+
const comparisonEntries = (0, react$1.useMemo)(() => {
|
|
4727
|
+
const primaryByGroup = new Map(primaryEntries.map(({ series, index }) => [series.group, {
|
|
4728
|
+
label: series.label,
|
|
4729
|
+
index
|
|
4730
|
+
}]));
|
|
4731
|
+
const entries = [];
|
|
4732
|
+
seriesWithVisibility.forEach(({ series, index, isVisible }) => {
|
|
4733
|
+
if (!isVisible || series.options?.type !== "comparison") return;
|
|
4734
|
+
const primary = primaryByGroup.get(series.group) ?? (primaryEntries.length === 1 ? {
|
|
4735
|
+
label: primaryEntries[0].series.label,
|
|
4736
|
+
index: primaryEntries[0].index
|
|
4737
|
+
} : void 0);
|
|
4738
|
+
if (!primary || !primaryKeys.includes(primary.label)) return;
|
|
4739
|
+
entries.push({
|
|
4740
|
+
series,
|
|
4741
|
+
index,
|
|
4742
|
+
primaryKey: primary.label,
|
|
4743
|
+
primaryIndex: primary.index
|
|
4744
|
+
});
|
|
4745
|
+
});
|
|
4746
|
+
return entries;
|
|
4747
|
+
}, [
|
|
4748
|
+
seriesWithVisibility,
|
|
4749
|
+
primaryEntries,
|
|
4750
|
+
primaryKeys
|
|
4751
|
+
]);
|
|
4752
|
+
const comparisonWidthFactor = (0, react$1.useMemo)(() => {
|
|
4753
|
+
if (comparisonEntries.length === 0) return void 0;
|
|
4754
|
+
return getElementStyles({
|
|
4755
|
+
data: comparisonEntries[0].series,
|
|
4756
|
+
index: comparisonEntries[0].index
|
|
4757
|
+
}).barStyles?.widthFactor ?? 1.5;
|
|
4758
|
+
}, [comparisonEntries, getElementStyles]);
|
|
4759
|
+
const groupPadding = (0, react$1.useMemo)(() => {
|
|
4760
|
+
const basePadding = chartOptions.barGroup.padding;
|
|
4761
|
+
if (!comparisonWidthFactor || comparisonWidthFactor <= 1) return basePadding;
|
|
4762
|
+
const p = 1 - (1 - COMPARISON_INNER_GAP) / comparisonWidthFactor;
|
|
4763
|
+
return Math.min(Math.max(p, basePadding), MAX_GROUP_PADDING);
|
|
4764
|
+
}, [chartOptions.barGroup.padding, comparisonWidthFactor]);
|
|
4765
|
+
const { xScale, yScale } = (0, react$1.useMemo)(() => {
|
|
4766
|
+
if (comparisonEntries.length === 0) return {
|
|
4767
|
+
xScale: chartOptions.xScale,
|
|
4768
|
+
yScale: chartOptions.yScale
|
|
4769
|
+
};
|
|
4770
|
+
const tighten = (scale) => ({
|
|
4771
|
+
...scale,
|
|
4772
|
+
paddingInner: (scale.paddingInner ?? .1) * COMPARISON_TICK_GAP_FACTOR
|
|
4773
|
+
});
|
|
4774
|
+
return horizontal ? {
|
|
4775
|
+
xScale: chartOptions.xScale,
|
|
4776
|
+
yScale: tighten(chartOptions.yScale)
|
|
4777
|
+
} : {
|
|
4778
|
+
xScale: tighten(chartOptions.xScale),
|
|
4779
|
+
yScale: chartOptions.yScale
|
|
4780
|
+
};
|
|
4781
|
+
}, [
|
|
4782
|
+
comparisonEntries.length,
|
|
4783
|
+
chartOptions.xScale,
|
|
4784
|
+
chartOptions.yScale,
|
|
4785
|
+
horizontal
|
|
4786
|
+
]);
|
|
4517
4787
|
const getBarBackground = (0, react$1.useCallback)((index) => () => withPatterns ? `url(#${getPatternId(chartId, index)})` : getElementStyles({
|
|
4518
4788
|
data: dataSorted[index],
|
|
4519
4789
|
index
|
|
@@ -4523,26 +4793,43 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4523
4793
|
dataSorted,
|
|
4524
4794
|
chartId
|
|
4525
4795
|
]);
|
|
4796
|
+
const resolveComparisonFill = (0, react$1.useCallback)((entry) => withPatterns ? `url(#${getPatternId(chartId, entry.primaryIndex)})` : getElementStyles({
|
|
4797
|
+
data: entry.series,
|
|
4798
|
+
index: entry.index
|
|
4799
|
+
}).color, [
|
|
4800
|
+
withPatterns,
|
|
4801
|
+
chartId,
|
|
4802
|
+
getElementStyles
|
|
4803
|
+
]);
|
|
4526
4804
|
const renderDefaultTooltip = (0, react$1.useCallback)(({ tooltipData }) => {
|
|
4527
4805
|
const nearestDatum = tooltipData?.nearestDatum?.datum;
|
|
4528
4806
|
if (!nearestDatum) return null;
|
|
4807
|
+
const primaryKey = tooltipData?.nearestDatum?.key;
|
|
4808
|
+
const categoryLabel = chartOptions.tooltip.labelFormatter(nearestDatum.label || (nearestDatum.date ? nearestDatum.date.getTime() : 0), 0, []);
|
|
4809
|
+
const comparisonEntry = comparisonEntries.find((entry) => entry.primaryKey === primaryKey);
|
|
4810
|
+
const comparisonDatum = comparisonEntry?.series.data.find((point) => {
|
|
4811
|
+
const p = point;
|
|
4812
|
+
return nearestDatum.label != null ? p.label === nearestDatum.label : !!nearestDatum.date && !!p.date && p.date.getTime() === nearestDatum.date.getTime();
|
|
4813
|
+
});
|
|
4814
|
+
if (comparisonEntry && comparisonDatum && comparisonDatum.value != null) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4815
|
+
className: bar_chart_module_default["bar-chart__tooltip"],
|
|
4816
|
+
children: [
|
|
4817
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4818
|
+
className: bar_chart_module_default["bar-chart__tooltip-header"],
|
|
4819
|
+
children: categoryLabel
|
|
4820
|
+
}),
|
|
4821
|
+
renderTooltipRow(primaryKey, (0, _automattic_number_formatters.formatNumber)(nearestDatum.value)),
|
|
4822
|
+
renderTooltipRow(comparisonEntry.series.label, (0, _automattic_number_formatters.formatNumber)(comparisonDatum.value))
|
|
4823
|
+
]
|
|
4824
|
+
});
|
|
4529
4825
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4530
4826
|
className: bar_chart_module_default["bar-chart__tooltip"],
|
|
4531
4827
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4532
4828
|
className: bar_chart_module_default["bar-chart__tooltip-header"],
|
|
4533
|
-
children:
|
|
4534
|
-
}),
|
|
4535
|
-
className: bar_chart_module_default["bar-chart__tooltip-row"],
|
|
4536
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4537
|
-
className: bar_chart_module_default["bar-chart__tooltip-label"],
|
|
4538
|
-
children: [chartOptions.tooltip.labelFormatter(nearestDatum.label || (nearestDatum.date ? nearestDatum.date.getTime() : 0), 0, []), ":"]
|
|
4539
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4540
|
-
className: bar_chart_module_default["bar-chart__tooltip-value"],
|
|
4541
|
-
children: (0, _automattic_number_formatters.formatNumber)(nearestDatum.value)
|
|
4542
|
-
})]
|
|
4543
|
-
})]
|
|
4829
|
+
children: primaryKey
|
|
4830
|
+
}), renderTooltipRow(categoryLabel, (0, _automattic_number_formatters.formatNumber)(nearestDatum.value))]
|
|
4544
4831
|
});
|
|
4545
|
-
}, [chartOptions.tooltip]);
|
|
4832
|
+
}, [chartOptions.tooltip, comparisonEntries]);
|
|
4546
4833
|
const renderPattern = (0, react$1.useCallback)((index, color) => {
|
|
4547
4834
|
const patternType = index % 4;
|
|
4548
4835
|
const id = getPatternId(chartId, index);
|
|
@@ -4579,8 +4866,10 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4579
4866
|
}
|
|
4580
4867
|
}, [chartId]);
|
|
4581
4868
|
const createPatternBorderStyle = (0, react$1.useCallback)((index, color) => {
|
|
4869
|
+
const patternId = getPatternId(chartId, index);
|
|
4582
4870
|
return `
|
|
4583
|
-
.visx-bar[fill="url(#${
|
|
4871
|
+
.visx-bar[fill="url(#${patternId})"],
|
|
4872
|
+
.bar-chart__comparison-bars rect[fill="url(#${patternId})"] {
|
|
4584
4873
|
stroke: ${color};
|
|
4585
4874
|
stroke-width: 1;
|
|
4586
4875
|
}
|
|
@@ -4588,11 +4877,13 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4588
4877
|
}, [chartId]);
|
|
4589
4878
|
const createKeyboardHighlightStyle = (0, react$1.useCallback)(() => {
|
|
4590
4879
|
if (selectedIndex === void 0) return "";
|
|
4591
|
-
const
|
|
4592
|
-
const
|
|
4593
|
-
const
|
|
4594
|
-
|
|
4595
|
-
if (dataPointIndex >=
|
|
4880
|
+
const primaryCount = primaryEntries.length;
|
|
4881
|
+
const maxDataPoints = Math.max(...primaryEntries.map((e) => e.series.data.length));
|
|
4882
|
+
const dataPointIndex = Math.floor(selectedIndex / primaryCount);
|
|
4883
|
+
const seriesIndex = selectedIndex % primaryCount;
|
|
4884
|
+
if (dataPointIndex >= maxDataPoints || seriesIndex >= primaryCount) return "";
|
|
4885
|
+
const seriesData = primaryEntries[seriesIndex]?.series;
|
|
4886
|
+
if (!seriesData || dataPointIndex >= seriesData.data.length) return "";
|
|
4596
4887
|
return `
|
|
4597
4888
|
.bar-chart[data-chart-id="bar-chart-${chartId}"] .visx-bar-group .visx-bar:nth-child(${seriesIndex * maxDataPoints + dataPointIndex + 1}) {
|
|
4598
4889
|
stroke: #005fcc;
|
|
@@ -4601,7 +4892,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4601
4892
|
`;
|
|
4602
4893
|
}, [
|
|
4603
4894
|
selectedIndex,
|
|
4604
|
-
|
|
4895
|
+
primaryEntries,
|
|
4605
4896
|
chartId
|
|
4606
4897
|
]);
|
|
4607
4898
|
const error = validateData$2(dataSorted);
|
|
@@ -4674,8 +4965,8 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4674
4965
|
...defaultMargin,
|
|
4675
4966
|
...margin
|
|
4676
4967
|
},
|
|
4677
|
-
xScale
|
|
4678
|
-
yScale
|
|
4968
|
+
xScale,
|
|
4969
|
+
yScale,
|
|
4679
4970
|
horizontal,
|
|
4680
4971
|
pointerEventsDataKey: "nearest",
|
|
4681
4972
|
children: [
|
|
@@ -4699,18 +4990,25 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4699
4990
|
height: chartHeight,
|
|
4700
4991
|
children: (0, _wordpress_i18n.__)("All series are hidden. Click legend items to show data.", "jetpack-charts")
|
|
4701
4992
|
}) : null,
|
|
4993
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComparisonBars, {
|
|
4994
|
+
comparisonEntries,
|
|
4995
|
+
primaryKeys,
|
|
4996
|
+
groupPadding,
|
|
4997
|
+
horizontal,
|
|
4998
|
+
xAccessor: chartOptions.accessors.xAccessor,
|
|
4999
|
+
yAccessor: chartOptions.accessors.yAccessor,
|
|
5000
|
+
getElementStyles,
|
|
5001
|
+
resolveFill: resolveComparisonFill
|
|
5002
|
+
}),
|
|
4702
5003
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.BarGroup, {
|
|
4703
|
-
padding:
|
|
4704
|
-
children:
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
colorAccessor: getBarBackground(index)
|
|
4712
|
-
}, seriesData?.label);
|
|
4713
|
-
})
|
|
5004
|
+
padding: groupPadding,
|
|
5005
|
+
children: primaryEntries.map(({ series: seriesData, index }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.BarSeries, {
|
|
5006
|
+
dataKey: seriesData?.label,
|
|
5007
|
+
data: seriesData.data,
|
|
5008
|
+
yAccessor: chartOptions.accessors.yAccessor,
|
|
5009
|
+
xAccessor: chartOptions.accessors.xAccessor,
|
|
5010
|
+
colorAccessor: getBarBackground(index)
|
|
5011
|
+
}, seriesData?.label))
|
|
4714
5012
|
}),
|
|
4715
5013
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.Axis, { ...chartOptions.axis.x }),
|
|
4716
5014
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_visx_xychart.Axis, { ...chartOptions.axis.y }),
|
|
@@ -4722,7 +5020,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
|
|
|
4722
5020
|
selectedIndex,
|
|
4723
5021
|
tooltipRef,
|
|
4724
5022
|
keyboardFocusedClassName: bar_chart_module_default["bar-chart__tooltip--keyboard-focused"],
|
|
4725
|
-
series:
|
|
5023
|
+
series: primarySeries,
|
|
4726
5024
|
mode: "individual"
|
|
4727
5025
|
})
|
|
4728
5026
|
]
|
|
@@ -5323,9 +5621,7 @@ const DEFAULT_BACKGROUND_COLOR = "#ffffff";
|
|
|
5323
5621
|
*/
|
|
5324
5622
|
const GeoChartInternal = ({ className, data, width, height, region = "world", resolution = "countries", renderPlaceholder }) => {
|
|
5325
5623
|
const { getElementStyles, theme: { geoChart: { featureFillColor }, backgroundColor } } = useGlobalChartsContext();
|
|
5326
|
-
const loadingPlaceholder = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
5327
|
-
align: "center",
|
|
5328
|
-
justify: "center",
|
|
5624
|
+
const loadingPlaceholder = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Center, {
|
|
5329
5625
|
className: (0, clsx.default)("geo-chart", geo_chart_module_default.container, className),
|
|
5330
5626
|
style: {
|
|
5331
5627
|
width,
|
|
@@ -5383,9 +5679,7 @@ const GeoChartInternal = ({ className, data, width, height, region = "world", re
|
|
|
5383
5679
|
defaultFillColorHex,
|
|
5384
5680
|
sanitizedData.hasHtmlTooltips
|
|
5385
5681
|
]);
|
|
5386
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
5387
|
-
align: "center",
|
|
5388
|
-
justify: "center",
|
|
5682
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Center, {
|
|
5389
5683
|
className: (0, clsx.default)("geo-chart", geo_chart_module_default.container, className),
|
|
5390
5684
|
style: {
|
|
5391
5685
|
width,
|
|
@@ -8432,7 +8726,6 @@ function RadialWipeAnimation({ id, radius, innerRadius = 0, durationMs = 1e3, wi
|
|
|
8432
8726
|
//#region src/charts/pie-chart/pie-chart.module.scss
|
|
8433
8727
|
var pie_chart_module_default = {
|
|
8434
8728
|
"pie-chart": "a8ccharts-gnszbG-pie-chart",
|
|
8435
|
-
"pie-chart__centering": "a8ccharts-gnszbG-pie-chart__centering",
|
|
8436
8729
|
"pie-chart--responsive": "a8ccharts-gnszbG-pie-chart--responsive"
|
|
8437
8730
|
};
|
|
8438
8731
|
//#endregion
|
|
@@ -8597,11 +8890,8 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
|
|
|
8597
8890
|
const innerRadius = thickness === 0 ? 0 : outerRadius * (1 - thickness);
|
|
8598
8891
|
const maxCornerRadius = (outerRadius - innerRadius) / 2;
|
|
8599
8892
|
const cornerRadius = cornerScale ? Math.min(cornerScale * outerRadius, maxCornerRadius) : 0;
|
|
8600
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
8893
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Center, {
|
|
8601
8894
|
ref: containerRef,
|
|
8602
|
-
align: "center",
|
|
8603
|
-
justify: "center",
|
|
8604
|
-
className: pie_chart_module_default["pie-chart__centering"],
|
|
8605
8895
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
8606
8896
|
viewBox: `0 0 ${width} ${height}`,
|
|
8607
8897
|
preserveAspectRatio: "xMidYMid meet",
|
|
@@ -8714,7 +9004,6 @@ var pie_semi_circle_chart_module_default = {
|
|
|
8714
9004
|
"label": "a8ccharts-YtTOxW-label",
|
|
8715
9005
|
"note": "a8ccharts-YtTOxW-note",
|
|
8716
9006
|
"pie-semi-circle-chart": "a8ccharts-YtTOxW-pie-semi-circle-chart",
|
|
8717
|
-
"pie-semi-circle-chart__centering": "a8ccharts-YtTOxW-pie-semi-circle-chart__centering",
|
|
8718
9007
|
"pie-semi-circle-chart--responsive": "a8ccharts-YtTOxW-pie-semi-circle-chart--responsive"
|
|
8719
9008
|
};
|
|
8720
9009
|
//#endregion
|
|
@@ -8894,11 +9183,8 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
|
|
|
8894
9183
|
const height = width / 2;
|
|
8895
9184
|
const radius = height;
|
|
8896
9185
|
const innerRadius = radius * (1 - thickness);
|
|
8897
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
9186
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Center, {
|
|
8898
9187
|
ref: containerRef,
|
|
8899
|
-
align: "center",
|
|
8900
|
-
justify: "center",
|
|
8901
|
-
className: pie_semi_circle_chart_module_default["pie-semi-circle-chart__centering"],
|
|
8902
9188
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
8903
9189
|
width,
|
|
8904
9190
|
height,
|