@automattic/charts 4.8.0 → 4.10.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 +28 -0
- package/dist/index.cjs +766 -277
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +72 -8
- package/dist/index.d.cts +54 -15
- package/dist/index.d.ts +54 -15
- package/dist/index.js +770 -281
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/charts/area-chart/area-chart.tsx +7 -3
- package/src/charts/area-chart/test/area-chart.test.tsx +15 -14
- package/src/charts/area-chart/test/tooltip-resolution.test.tsx +2 -2
- package/src/charts/bar-chart/bar-chart.tsx +12 -4
- package/src/charts/bar-chart/test/bar-chart.test.tsx +74 -63
- package/src/charts/bar-list-chart/bar-list-chart.tsx +3 -0
- package/src/charts/bar-list-chart/test/bar-list-chart.test.tsx +3 -1
- package/src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx +23 -7
- package/src/charts/conversion-funnel-chart/test/conversion-funnel-chart.test.tsx +22 -0
- package/src/charts/conversion-funnel-chart/types.ts +1 -1
- package/src/charts/geo-chart/geo-chart.tsx +17 -2
- package/src/charts/geo-chart/test/geo-chart.test.tsx +9 -4
- package/src/charts/geo-chart/types.ts +1 -1
- package/src/charts/heatmap-chart/heatmap-chart.module.scss +10 -4
- package/src/charts/heatmap-chart/heatmap-chart.tsx +144 -37
- package/src/charts/heatmap-chart/private/column-groups.ts +79 -8
- package/src/charts/heatmap-chart/private/fit-compact-cells.ts +72 -0
- package/src/charts/heatmap-chart/private/heatmap-legend.tsx +14 -2
- package/src/charts/heatmap-chart/private/index.ts +4 -2
- package/src/charts/heatmap-chart/test/column-groups.test.ts +41 -4
- package/src/charts/heatmap-chart/test/fit-compact-cells.test.ts +59 -0
- package/src/charts/heatmap-chart/test/heatmap-chart.test.tsx +132 -7
- package/src/charts/heatmap-chart/types.ts +2 -2
- package/src/charts/leaderboard-chart/hooks/use-fitted-row-count.ts +2 -2
- package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +52 -4
- package/src/charts/leaderboard-chart/leaderboard-chart.tsx +60 -9
- package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +80 -1
- package/src/charts/leaderboard-chart/types.ts +7 -1
- package/src/charts/line-chart/line-chart.tsx +8 -2
- package/src/charts/line-chart/private/line-chart-annotation-label-popover.tsx +19 -9
- package/src/charts/line-chart/test/default-tooltip-formatting.test.tsx +1 -1
- package/src/charts/line-chart/test/line-chart.test.tsx +37 -35
- package/src/charts/line-chart/test/tooltip-resolution.test.tsx +2 -2
- package/src/charts/line-chart/types.ts +3 -3
- package/src/charts/pie-chart/pie-chart.module.scss +3 -0
- package/src/charts/pie-chart/pie-chart.tsx +144 -139
- package/src/charts/pie-chart/test/pie-chart.test.tsx +167 -0
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss +3 -0
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +117 -120
- package/src/charts/pie-semi-circle-chart/test/pie-semi-circle-chart.test.tsx +54 -0
- package/src/charts/private/chart-composition/use-chart-children.ts +11 -6
- package/src/charts/private/pie-keyboard-navigation/index.ts +4 -0
- package/src/charts/private/pie-keyboard-navigation/order-arcs-for-navigation.ts +10 -0
- package/src/charts/private/pie-keyboard-navigation/pie-keyboard-navigation.module.scss +16 -0
- package/src/charts/private/pie-keyboard-navigation/pie-selection-announcement.tsx +14 -0
- package/src/charts/private/pie-keyboard-navigation/pie-selection-output.tsx +82 -0
- package/src/charts/private/pie-keyboard-navigation/pie-tooltip.tsx +49 -0
- package/src/charts/private/pie-keyboard-navigation/selected-segment-ring.tsx +47 -0
- package/src/charts/private/pie-keyboard-navigation/test/order-arcs-for-navigation.test.ts +34 -0
- package/src/charts/private/pie-keyboard-navigation/test/selected-segment-ring.test.ts +14 -0
- package/src/charts/private/pie-keyboard-navigation/use-pie-keyboard-navigation.ts +139 -0
- package/src/charts/private/x-zoom/test/x-zoom.test.tsx +3 -2
- package/src/charts/test/accessible-name.test.tsx +181 -0
- package/src/components/legend/hooks/test/use-chart-legend-items.test.tsx +63 -3
- package/src/components/legend/hooks/use-chart-legend-items.ts +63 -1
- package/src/components/legend/private/base-legend.tsx +27 -15
- package/src/components/legend/test/legend.test.tsx +42 -0
- package/src/components/legend/types.ts +2 -0
- package/src/components/tooltip/test/xy-chart-tooltip.test.tsx +20 -19
- package/src/components/tooltip/xy-chart-tooltip.tsx +3 -3
- package/src/hooks/test/use-xychart-theme.test.tsx +22 -0
- package/src/hooks/use-xychart-theme.ts +33 -2
- package/src/index.ts +1 -0
- package/src/types.ts +37 -3
- package/src/utils/resolve-font-size.ts +9 -10
- package/src/utils/test/resolve-font-size.test.ts +11 -2
package/package.json
CHANGED
|
@@ -52,6 +52,7 @@ const AreaChartInternal = forwardRef< ChartInstanceRef, AreaChartProps >(
|
|
|
52
52
|
(
|
|
53
53
|
{
|
|
54
54
|
data,
|
|
55
|
+
ariaLabel,
|
|
55
56
|
chartId: providedChartId,
|
|
56
57
|
width,
|
|
57
58
|
height,
|
|
@@ -261,8 +262,9 @@ const AreaChartInternal = forwardRef< ChartInstanceRef, AreaChartProps >(
|
|
|
261
262
|
glyphSize: 0,
|
|
262
263
|
collapseGroups: legend.collapseGroups ?? false,
|
|
263
264
|
comparisonItem: legend.comparisonItem ?? false,
|
|
265
|
+
comparisonSeriesItems: legend.comparisonSeriesItems,
|
|
264
266
|
} ),
|
|
265
|
-
[ legend.collapseGroups, legend.comparisonItem ]
|
|
267
|
+
[ legend.collapseGroups, legend.comparisonItem, legend.comparisonSeriesItems ]
|
|
266
268
|
);
|
|
267
269
|
const legendItems = useChartLegendItems( dataSorted, legendOptions, legendShape );
|
|
268
270
|
|
|
@@ -421,10 +423,11 @@ const AreaChartInternal = forwardRef< ChartInstanceRef, AreaChartProps >(
|
|
|
421
423
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
422
424
|
|
|
423
425
|
return (
|
|
426
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- the application role hands arrow keys to the chart's point navigation.
|
|
424
427
|
<div
|
|
425
428
|
ref={ chartRef }
|
|
426
|
-
role="
|
|
427
|
-
aria-label={ __( 'Area chart', 'jetpack-charts' ) }
|
|
429
|
+
role="application"
|
|
430
|
+
aria-label={ ariaLabel ?? __( 'Area chart', 'jetpack-charts' ) }
|
|
428
431
|
tabIndex={ 0 }
|
|
429
432
|
onKeyDown={ onChartKeyDown }
|
|
430
433
|
onFocus={ onChartFocus }
|
|
@@ -434,6 +437,7 @@ const AreaChartInternal = forwardRef< ChartInstanceRef, AreaChartProps >(
|
|
|
434
437
|
<div className={ plotStyles[ 'xy-plot' ] }>
|
|
435
438
|
{ zoomable && zoom.domain && <ZoomResetButton onClick={ zoom.reset } /> }
|
|
436
439
|
<XYChart
|
|
440
|
+
accessibilityLabel=""
|
|
437
441
|
theme={ theme }
|
|
438
442
|
width={ width }
|
|
439
443
|
height={ chartHeight }
|
|
@@ -53,13 +53,13 @@ describe( 'AreaChart', () => {
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
test.each( [ [ 'Escape', '{Escape}' ] ] )(
|
|
56
|
-
'returns focus to the
|
|
56
|
+
'returns focus to the chart after %s',
|
|
57
57
|
async ( _name, keys ) => {
|
|
58
58
|
jest.useFakeTimers();
|
|
59
59
|
try {
|
|
60
60
|
const user = userEvent.setup( { advanceTimers: jest.advanceTimersByTime } );
|
|
61
61
|
renderWithProvider();
|
|
62
|
-
const chart = screen.getByRole( '
|
|
62
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
63
63
|
|
|
64
64
|
await user.tab();
|
|
65
65
|
expect( chart ).toHaveFocus();
|
|
@@ -139,7 +139,7 @@ describe( 'AreaChart', () => {
|
|
|
139
139
|
|
|
140
140
|
test( 'renders with valid data', () => {
|
|
141
141
|
renderWithProvider();
|
|
142
|
-
expect( screen.getByRole( '
|
|
142
|
+
expect( screen.getByRole( 'application', { name: /area chart/i } ) ).toBeInTheDocument();
|
|
143
143
|
} );
|
|
144
144
|
} );
|
|
145
145
|
|
|
@@ -203,7 +203,7 @@ describe( 'AreaChart', () => {
|
|
|
203
203
|
],
|
|
204
204
|
} );
|
|
205
205
|
|
|
206
|
-
const chart = screen.getByRole( '
|
|
206
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
207
207
|
const ticks = within( chart )
|
|
208
208
|
.getAllByText( /^-?[\d.,]+$/ )
|
|
209
209
|
.map( el => el.textContent );
|
|
@@ -228,7 +228,7 @@ describe( 'AreaChart', () => {
|
|
|
228
228
|
},
|
|
229
229
|
} );
|
|
230
230
|
|
|
231
|
-
const chart = screen.getByRole( '
|
|
231
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
232
232
|
expect( within( chart ).getAllByText( /^\d+%$/ ) ).toHaveLength( 6 );
|
|
233
233
|
} );
|
|
234
234
|
|
|
@@ -254,7 +254,7 @@ describe( 'AreaChart', () => {
|
|
|
254
254
|
],
|
|
255
255
|
} );
|
|
256
256
|
|
|
257
|
-
const chart = screen.getByRole( '
|
|
257
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
258
258
|
expect( within( chart ).getAllByText( /^-?[\d.,]+$/ ).length ).toBeGreaterThan( 2 );
|
|
259
259
|
} );
|
|
260
260
|
} );
|
|
@@ -275,7 +275,7 @@ describe( 'AreaChart', () => {
|
|
|
275
275
|
|
|
276
276
|
test( 'accepts custom stackOffset', () => {
|
|
277
277
|
renderWithProvider( { stackOffset: 'expand' } );
|
|
278
|
-
expect( screen.getByRole( '
|
|
278
|
+
expect( screen.getByRole( 'application', { name: /area chart/i } ) ).toBeInTheDocument();
|
|
279
279
|
} );
|
|
280
280
|
} );
|
|
281
281
|
|
|
@@ -344,7 +344,7 @@ describe( 'AreaChart', () => {
|
|
|
344
344
|
|
|
345
345
|
// Open a tooltip via keyboard navigation, then verify the hidden
|
|
346
346
|
// series' label is absent from the rendered tooltip rows.
|
|
347
|
-
const chart = screen.getByRole( '
|
|
347
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
348
348
|
chart.focus();
|
|
349
349
|
await user.keyboard( '{ArrowRight}' );
|
|
350
350
|
|
|
@@ -364,7 +364,7 @@ describe( 'AreaChart', () => {
|
|
|
364
364
|
} );
|
|
365
365
|
|
|
366
366
|
await user.click( screen.getByText( 'Series A' ) );
|
|
367
|
-
const chart = screen.getByRole( '
|
|
367
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
368
368
|
chart.focus();
|
|
369
369
|
await user.keyboard( '{ArrowRight}' );
|
|
370
370
|
|
|
@@ -762,7 +762,7 @@ describe( 'AreaChart', () => {
|
|
|
762
762
|
context?.toggleSeriesVisibility( chartId, 'Series A' );
|
|
763
763
|
} );
|
|
764
764
|
|
|
765
|
-
const chart = screen.getByRole( '
|
|
765
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
766
766
|
chart.focus();
|
|
767
767
|
await user.keyboard( '{ArrowRight}' );
|
|
768
768
|
|
|
@@ -775,16 +775,17 @@ describe( 'AreaChart', () => {
|
|
|
775
775
|
describe( 'Without GlobalChartsProvider', () => {
|
|
776
776
|
test( 'self-wraps in a provider when none is present', () => {
|
|
777
777
|
render( <AreaChartUnresponsive { ...defaultProps } /> );
|
|
778
|
-
expect( screen.getByRole( '
|
|
778
|
+
expect( screen.getByRole( 'application', { name: /area chart/i } ) ).toBeInTheDocument();
|
|
779
779
|
} );
|
|
780
780
|
} );
|
|
781
781
|
|
|
782
782
|
describe( 'Accessibility', () => {
|
|
783
783
|
test( 'chart container has expected ARIA attributes', () => {
|
|
784
784
|
renderWithProvider();
|
|
785
|
-
const chart = screen.getByRole( '
|
|
785
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
786
786
|
expect( chart ).toHaveAttribute( 'tabIndex', '0' );
|
|
787
787
|
expect( chart ).toHaveAttribute( 'aria-label', 'Area chart' );
|
|
788
|
+
expect( screen.queryByLabelText( 'XYChart' ) ).not.toBeInTheDocument();
|
|
788
789
|
} );
|
|
789
790
|
} );
|
|
790
791
|
|
|
@@ -822,7 +823,7 @@ describe( 'AreaChart', () => {
|
|
|
822
823
|
// surface the visx TooltipContext state in a jsdom environment.
|
|
823
824
|
const focusFirstDatum = async () => {
|
|
824
825
|
const user = userEvent.setup();
|
|
825
|
-
const chart = screen.getByRole( '
|
|
826
|
+
const chart = screen.getByRole( 'application', { name: /area chart/i } );
|
|
826
827
|
chart.focus();
|
|
827
828
|
await user.keyboard( '{ArrowRight}' );
|
|
828
829
|
};
|
|
@@ -972,7 +973,7 @@ describe( 'AreaChart', () => {
|
|
|
972
973
|
|
|
973
974
|
// The visx grid has no role/testid, so query its internal class from within the plot.
|
|
974
975
|
/* eslint-disable testing-library/no-node-access */
|
|
975
|
-
const plot = screen.getByRole( '
|
|
976
|
+
const plot = screen.getByRole( 'application' );
|
|
976
977
|
expect( plot.querySelector( '.visx-rows' ) ).toBeInTheDocument();
|
|
977
978
|
|
|
978
979
|
const buttons = screen.getAllByRole( 'button' );
|
|
@@ -28,7 +28,7 @@ describe( 'area chart tooltip bucket info', () => {
|
|
|
28
28
|
</GlobalChartsProvider>
|
|
29
29
|
);
|
|
30
30
|
|
|
31
|
-
screen.getByRole( '
|
|
31
|
+
screen.getByRole( 'application', { name: /area chart/i } ).focus();
|
|
32
32
|
await user.keyboard( '{ArrowRight}' );
|
|
33
33
|
|
|
34
34
|
expect( screen.getByTestId( 'chart-tooltip-0' ) ).toHaveTextContent( '2.8.2026, 09 Uhr' );
|
|
@@ -61,7 +61,7 @@ describe( 'area chart tooltip bucket info', () => {
|
|
|
61
61
|
</GlobalChartsProvider>
|
|
62
62
|
);
|
|
63
63
|
|
|
64
|
-
screen.getByRole( '
|
|
64
|
+
screen.getByRole( 'application', { name: /area chart/i } ).focus();
|
|
65
65
|
await user.keyboard( '{ArrowRight}' );
|
|
66
66
|
|
|
67
67
|
expect( screen.getByTestId( 'chart-tooltip-0' ) ).not.toHaveTextContent( 'Uhr' );
|
|
@@ -100,6 +100,7 @@ const renderTooltipRow = ( label: string | undefined, value: string ) => (
|
|
|
100
100
|
|
|
101
101
|
const BarChartInternal: FC< BarChartProps > = ( {
|
|
102
102
|
data,
|
|
103
|
+
ariaLabel,
|
|
103
104
|
chartId: providedChartId,
|
|
104
105
|
width,
|
|
105
106
|
height,
|
|
@@ -138,6 +139,7 @@ const BarChartInternal: FC< BarChartProps > = ( {
|
|
|
138
139
|
const legendInteractive = legend.interactive ?? false;
|
|
139
140
|
const legendCollapseGroups = legend.collapseGroups ?? false;
|
|
140
141
|
const legendComparisonItem = legend.comparisonItem ?? false;
|
|
142
|
+
const legendComparisonSeriesItems = legend.comparisonSeriesItems;
|
|
141
143
|
const horizontal = orientation === 'horizontal';
|
|
142
144
|
const chartId = useChartId( providedChartId );
|
|
143
145
|
const hiddenSeries = useDefaultHiddenSeries( chartId, defaultHiddenSeries );
|
|
@@ -158,8 +160,12 @@ const BarChartInternal: FC< BarChartProps > = ( {
|
|
|
158
160
|
|
|
159
161
|
// Create legend items using the reusable hook
|
|
160
162
|
const legendOptions = useMemo(
|
|
161
|
-
() => ( {
|
|
162
|
-
|
|
163
|
+
() => ( {
|
|
164
|
+
collapseGroups: legendCollapseGroups,
|
|
165
|
+
comparisonItem: legendComparisonItem,
|
|
166
|
+
comparisonSeriesItems: legendComparisonSeriesItems,
|
|
167
|
+
} ),
|
|
168
|
+
[ legendCollapseGroups, legendComparisonItem, legendComparisonSeriesItems ]
|
|
163
169
|
);
|
|
164
170
|
const legendItems = useChartLegendItems( dataSorted, legendOptions );
|
|
165
171
|
|
|
@@ -603,10 +609,11 @@ const BarChartInternal: FC< BarChartProps > = ( {
|
|
|
603
609
|
const chartHeight = contentHeight > 0 ? contentHeight : height;
|
|
604
610
|
|
|
605
611
|
return (
|
|
612
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- the application role hands arrow keys to the chart's point navigation.
|
|
606
613
|
<div
|
|
607
|
-
role="
|
|
614
|
+
role="application"
|
|
608
615
|
ref={ chartRef }
|
|
609
|
-
aria-label={ __( 'Bar chart', 'jetpack-charts' ) }
|
|
616
|
+
aria-label={ ariaLabel ?? __( 'Bar chart', 'jetpack-charts' ) }
|
|
610
617
|
tabIndex={ 0 }
|
|
611
618
|
onKeyDown={ onChartKeyDown }
|
|
612
619
|
onFocus={ onChartFocus }
|
|
@@ -615,6 +622,7 @@ const BarChartInternal: FC< BarChartProps > = ( {
|
|
|
615
622
|
{ chartHeight > 0 && (
|
|
616
623
|
<div className={ plotStyles[ 'xy-plot' ] }>
|
|
617
624
|
<XYChart
|
|
625
|
+
accessibilityLabel=""
|
|
618
626
|
theme={ theme }
|
|
619
627
|
width={ width }
|
|
620
628
|
height={ chartHeight }
|