@automattic/charts 0.57.0 → 0.58.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 +16 -2
- package/dist/charts/bar-chart/index.cjs +7 -5
- package/dist/charts/bar-chart/index.cjs.map +1 -1
- package/dist/charts/bar-chart/index.css +12 -24
- package/dist/charts/bar-chart/index.css.map +1 -1
- package/dist/charts/bar-chart/index.d.cts +3 -4
- package/dist/charts/bar-chart/index.d.ts +3 -4
- package/dist/charts/bar-chart/index.js +6 -4
- package/dist/charts/bar-list-chart/index.cjs +8 -6
- package/dist/charts/bar-list-chart/index.cjs.map +1 -1
- package/dist/charts/bar-list-chart/index.css +12 -24
- package/dist/charts/bar-list-chart/index.css.map +1 -1
- package/dist/charts/bar-list-chart/index.d.cts +3 -3
- package/dist/charts/bar-list-chart/index.d.ts +3 -3
- package/dist/charts/bar-list-chart/index.js +7 -5
- package/dist/charts/conversion-funnel-chart/index.cjs +5 -5
- package/dist/charts/conversion-funnel-chart/index.css +0 -94
- package/dist/charts/conversion-funnel-chart/index.css.map +1 -1
- package/dist/charts/conversion-funnel-chart/index.d.cts +1 -1
- package/dist/charts/conversion-funnel-chart/index.d.ts +1 -1
- package/dist/charts/conversion-funnel-chart/index.js +4 -4
- package/dist/charts/geo-chart/index.cjs +4 -4
- package/dist/charts/geo-chart/index.css +0 -94
- package/dist/charts/geo-chart/index.css.map +1 -1
- package/dist/charts/geo-chart/index.d.cts +1 -1
- package/dist/charts/geo-chart/index.d.ts +1 -1
- package/dist/charts/geo-chart/index.js +3 -3
- package/dist/charts/leaderboard-chart/index.cjs +7 -6
- package/dist/charts/leaderboard-chart/index.cjs.map +1 -1
- package/dist/charts/leaderboard-chart/index.css +12 -24
- package/dist/charts/leaderboard-chart/index.css.map +1 -1
- package/dist/charts/leaderboard-chart/index.d.cts +3 -3
- package/dist/charts/leaderboard-chart/index.d.ts +3 -3
- package/dist/charts/leaderboard-chart/index.js +6 -5
- package/dist/charts/line-chart/index.cjs +7 -5
- package/dist/charts/line-chart/index.cjs.map +1 -1
- package/dist/charts/line-chart/index.css +12 -24
- package/dist/charts/line-chart/index.css.map +1 -1
- package/dist/charts/line-chart/index.d.cts +3 -4
- package/dist/charts/line-chart/index.d.ts +3 -4
- package/dist/charts/line-chart/index.js +6 -4
- package/dist/charts/pie-chart/index.cjs +7 -6
- package/dist/charts/pie-chart/index.cjs.map +1 -1
- package/dist/charts/pie-chart/index.css +12 -24
- package/dist/charts/pie-chart/index.css.map +1 -1
- package/dist/charts/pie-chart/index.d.cts +7 -13
- package/dist/charts/pie-chart/index.d.ts +7 -13
- package/dist/charts/pie-chart/index.js +6 -5
- package/dist/charts/pie-semi-circle-chart/index.cjs +7 -6
- package/dist/charts/pie-semi-circle-chart/index.cjs.map +1 -1
- package/dist/charts/pie-semi-circle-chart/index.css +12 -24
- package/dist/charts/pie-semi-circle-chart/index.css.map +1 -1
- package/dist/charts/pie-semi-circle-chart/index.d.cts +7 -13
- package/dist/charts/pie-semi-circle-chart/index.d.ts +7 -13
- package/dist/charts/pie-semi-circle-chart/index.js +6 -5
- package/dist/charts/sparkline/index.cjs +8 -6
- package/dist/charts/sparkline/index.cjs.map +1 -1
- package/dist/charts/sparkline/index.css +12 -24
- package/dist/charts/sparkline/index.css.map +1 -1
- package/dist/charts/sparkline/index.js +7 -5
- package/dist/{chunk-32DH6JDF.js → chunk-2I67QUIV.js} +52 -420
- package/dist/chunk-2I67QUIV.js.map +1 -0
- package/dist/{chunk-WLODYNLB.js → chunk-2ICEEQOC.js} +31 -27
- package/dist/chunk-2ICEEQOC.js.map +1 -0
- package/dist/{chunk-IU4DYUAV.js → chunk-4B7BL2DD.js} +3 -3
- package/dist/{chunk-BCX5THDQ.js → chunk-4OXMTKAL.js} +24 -26
- package/dist/chunk-4OXMTKAL.js.map +1 -0
- package/dist/{chunk-4OPFE4RM.js → chunk-B6NLZFRW.js} +30 -27
- package/dist/chunk-B6NLZFRW.js.map +1 -0
- package/dist/{chunk-D2UH4CFE.cjs → chunk-BBAUQOW6.cjs} +9 -9
- package/dist/{chunk-D2UH4CFE.cjs.map → chunk-BBAUQOW6.cjs.map} +1 -1
- package/dist/{chunk-XKRJL2QT.cjs → chunk-CMMHCTBX.cjs} +45 -47
- package/dist/chunk-CMMHCTBX.cjs.map +1 -0
- package/dist/{chunk-YE2T52VZ.cjs → chunk-CPPXJATQ.cjs} +51 -47
- package/dist/chunk-CPPXJATQ.cjs.map +1 -0
- package/dist/{chunk-H2V4JMSA.js → chunk-DKU775VC.js} +3 -3
- package/dist/{chunk-ZH4F5RMG.cjs → chunk-GRA7Y2ZG.cjs} +46 -48
- package/dist/chunk-GRA7Y2ZG.cjs.map +1 -0
- package/dist/{chunk-DAU3HNEG.js → chunk-JJIMABHT.js} +9 -2
- package/dist/chunk-JJIMABHT.js.map +1 -0
- package/dist/{chunk-CZGYJKG6.js → chunk-KJHWXOCZ.js} +4 -4
- package/dist/{chunk-6CCZL2JJ.js → chunk-KRWGSOJ2.js} +30 -2
- package/dist/chunk-KRWGSOJ2.js.map +1 -0
- package/dist/{chunk-V36ERY7Y.js → chunk-LTFH7SEG.js} +24 -26
- package/dist/chunk-LTFH7SEG.js.map +1 -0
- package/dist/{chunk-PXLEMUGJ.js → chunk-MUNOKLLE.js} +3 -3
- package/dist/{chunk-VTS3PNMS.cjs → chunk-MXGLYWVP.cjs} +9 -2
- package/dist/chunk-MXGLYWVP.cjs.map +1 -0
- package/dist/{chunk-Z45KX47P.cjs → chunk-OYC34VTO.cjs} +154 -94
- package/dist/chunk-OYC34VTO.cjs.map +1 -0
- package/dist/{chunk-77OKCVQN.cjs → chunk-PQL5I3F6.cjs} +17 -17
- package/dist/{chunk-77OKCVQN.cjs.map → chunk-PQL5I3F6.cjs.map} +1 -1
- package/dist/{chunk-I35UYJJR.cjs → chunk-REZTQ4PH.cjs} +41 -21
- package/dist/chunk-REZTQ4PH.cjs.map +1 -0
- package/dist/{chunk-RCY6XLGU.cjs → chunk-TZRUHQOH.cjs} +36 -8
- package/dist/chunk-TZRUHQOH.cjs.map +1 -0
- package/dist/{chunk-2NCY7R4G.js → chunk-UTYVIOWZ.js} +111 -51
- package/dist/chunk-UTYVIOWZ.js.map +1 -0
- package/dist/{chunk-TO3OQBXG.cjs → chunk-W2LDIX26.cjs} +5 -5
- package/dist/{chunk-TO3OQBXG.cjs.map → chunk-W2LDIX26.cjs.map} +1 -1
- package/dist/{chunk-7FQX4ALL.cjs → chunk-WSG64BVN.cjs} +6 -6
- package/dist/{chunk-7FQX4ALL.cjs.map → chunk-WSG64BVN.cjs.map} +1 -1
- package/dist/chunk-WTQYGUNF.js +400 -0
- package/dist/chunk-WTQYGUNF.js.map +1 -0
- package/dist/{chunk-RHHVEJHJ.cjs → chunk-WYK7EL5R.cjs} +68 -436
- package/dist/chunk-WYK7EL5R.cjs.map +1 -0
- package/dist/{chunk-VJM5XCB4.cjs → chunk-XC4KHJYX.cjs} +49 -46
- package/dist/chunk-XC4KHJYX.cjs.map +1 -0
- package/dist/chunk-XVBH5XHE.cjs +400 -0
- package/dist/chunk-XVBH5XHE.cjs.map +1 -0
- package/dist/{chunk-Z26M4V2M.js → chunk-YAFQVVDI.js} +41 -21
- package/dist/chunk-YAFQVVDI.js.map +1 -0
- package/dist/components/legend/index.cjs +4 -3
- package/dist/components/legend/index.cjs.map +1 -1
- package/dist/components/legend/index.css +12 -24
- package/dist/components/legend/index.css.map +1 -1
- package/dist/components/legend/index.d.cts +4 -4
- package/dist/components/legend/index.d.ts +4 -4
- package/dist/components/legend/index.js +3 -2
- package/dist/components/tooltip/index.d.cts +1 -1
- package/dist/components/tooltip/index.d.ts +1 -1
- package/dist/hooks/index.cjs +3 -5
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.css +0 -94
- package/dist/hooks/index.css.map +1 -1
- package/dist/hooks/index.d.cts +3 -11
- package/dist/hooks/index.d.ts +3 -11
- package/dist/hooks/index.js +2 -4
- package/dist/index.cjs +18 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +12 -24
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +17 -15
- package/dist/{leaderboard-chart-DR7CGb0L.d.cts → leaderboard-chart-BSbg0ufV.d.cts} +3 -7
- package/dist/{leaderboard-chart-BKYYXcg2.d.ts → leaderboard-chart-odEYxxEC.d.ts} +3 -7
- package/dist/{legend-C2grwnWk.d.cts → legend-DFkosEvC.d.cts} +1 -1
- package/dist/{legend-Cj0xM5dU.d.ts → legend-DLswHhOk.d.ts} +1 -1
- package/dist/providers/index.cjs +3 -3
- package/dist/providers/index.css +0 -94
- package/dist/providers/index.css.map +1 -1
- package/dist/providers/index.d.cts +3 -3
- package/dist/providers/index.d.ts +3 -3
- package/dist/providers/index.js +2 -2
- package/dist/{themes-CyjKm-P_.d.cts → themes-D0qc5JaW.d.cts} +2 -2
- package/dist/{themes-BmVGrYnF.d.ts → themes-itO4Ht5g.d.ts} +2 -2
- package/dist/{types-KtOPPzPX.d.cts → types-B5f6XQ7Q.d.cts} +1 -1
- package/dist/{types-CuUEszrM.d.ts → types-BsHooDbM.d.ts} +1 -1
- package/dist/{types-I67mddpr.d.cts → types-BuSrRM4p.d.ts} +3 -32
- package/dist/{types-DZordNiO.d.cts → types-ChOUI9-N.d.cts} +80 -40
- package/dist/{types-DZordNiO.d.ts → types-ChOUI9-N.d.ts} +80 -40
- package/dist/{types-I67mddpr.d.ts → types-Dfw9VOKI.d.cts} +3 -32
- package/dist/utils/index.cjs +2 -2
- package/dist/utils/index.d.cts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/package.json +6 -6
- package/src/charts/bar-chart/bar-chart.tsx +17 -18
- package/src/charts/bar-chart/test/bar-chart.test.tsx +48 -31
- package/src/charts/leaderboard-chart/leaderboard-chart.tsx +38 -41
- package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +4 -5
- package/src/charts/leaderboard-chart/types.ts +1 -11
- package/src/charts/line-chart/line-chart.tsx +18 -16
- package/src/charts/line-chart/test/line-chart.test.tsx +49 -27
- package/src/charts/line-chart/types.ts +0 -1
- package/src/charts/pie-chart/pie-chart.tsx +23 -22
- package/src/charts/pie-chart/test/composition-api.test.tsx +41 -0
- package/src/charts/pie-chart/test/pie-chart.test.tsx +9 -9
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +21 -23
- package/src/charts/pie-semi-circle-chart/test/pie-semi-circle-chart.test.tsx +33 -5
- package/src/charts/private/chart-composition/index.ts +2 -0
- package/src/charts/private/chart-composition/render-legend-slot.ts +22 -0
- package/src/charts/private/chart-composition/test/render-legend-slot.test.tsx +60 -0
- package/src/charts/private/chart-composition/test/use-chart-children.test.tsx +91 -0
- package/src/charts/private/chart-composition/use-chart-children.ts +34 -2
- package/src/components/legend/index.ts +1 -8
- package/src/components/legend/private/base-legend.module.scss +19 -37
- package/src/components/legend/private/base-legend.tsx +0 -2
- package/src/components/legend/types.ts +7 -34
- package/src/hooks/index.ts +0 -1
- package/src/index.ts +1 -7
- package/src/types.ts +83 -38
- package/src/utils/date-parsing.ts +10 -1
- package/src/utils/test/date-parsing.test.ts +12 -0
- package/src/utils/test/resolve-css-var.test.ts +2 -2
- package/tsup.config.ts +1 -1
- package/dist/chunk-2NCY7R4G.js.map +0 -1
- package/dist/chunk-32DH6JDF.js.map +0 -1
- package/dist/chunk-4OPFE4RM.js.map +0 -1
- package/dist/chunk-6CCZL2JJ.js.map +0 -1
- package/dist/chunk-BCX5THDQ.js.map +0 -1
- package/dist/chunk-DAU3HNEG.js.map +0 -1
- package/dist/chunk-I35UYJJR.cjs.map +0 -1
- package/dist/chunk-RCY6XLGU.cjs.map +0 -1
- package/dist/chunk-RHHVEJHJ.cjs.map +0 -1
- package/dist/chunk-V36ERY7Y.js.map +0 -1
- package/dist/chunk-VJM5XCB4.cjs.map +0 -1
- package/dist/chunk-VTS3PNMS.cjs.map +0 -1
- package/dist/chunk-WLODYNLB.js.map +0 -1
- package/dist/chunk-XKRJL2QT.cjs.map +0 -1
- package/dist/chunk-YE2T52VZ.cjs.map +0 -1
- package/dist/chunk-Z26M4V2M.js.map +0 -1
- package/dist/chunk-Z45KX47P.cjs.map +0 -1
- package/dist/chunk-ZH4F5RMG.cjs.map +0 -1
- package/src/hooks/use-has-legend-child.ts +0 -22
- /package/dist/{chunk-IU4DYUAV.js.map → chunk-4B7BL2DD.js.map} +0 -0
- /package/dist/{chunk-H2V4JMSA.js.map → chunk-DKU775VC.js.map} +0 -0
- /package/dist/{chunk-CZGYJKG6.js.map → chunk-KJHWXOCZ.js.map} +0 -0
- /package/dist/{chunk-PXLEMUGJ.js.map → chunk-MUNOKLLE.js.map} +0 -0
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
useGlobalChartsTheme,
|
|
17
17
|
} from '../../providers';
|
|
18
18
|
import { formatMetricValue, attachSubComponents } from '../../utils';
|
|
19
|
-
import { useChartChildren } from '../private/chart-composition';
|
|
19
|
+
import { useChartChildren, renderLegendSlot } from '../private/chart-composition';
|
|
20
20
|
import { SingleChartContext } from '../private/single-chart-context';
|
|
21
21
|
import { withResponsive } from '../private/with-responsive';
|
|
22
22
|
import { useLeaderboardLegendItems } from './hooks';
|
|
@@ -110,31 +110,26 @@ const BarWithLabel = ( {
|
|
|
110
110
|
* LeaderboardChart component displays a ranked list of data with progress bars
|
|
111
111
|
* and optional comparison values.
|
|
112
112
|
*
|
|
113
|
-
* @param props
|
|
114
|
-
* @param props.data
|
|
115
|
-
* @param props.chartId
|
|
116
|
-
* @param props.width
|
|
117
|
-
* @param props.height
|
|
118
|
-
* @param props.withComparison
|
|
119
|
-
* @param props.withOverlayLabel
|
|
120
|
-
* @param props.primaryColor
|
|
121
|
-
* @param props.secondaryColor
|
|
122
|
-
* @param props.valueFormatter
|
|
123
|
-
* @param props.deltaFormatter
|
|
124
|
-
* @param props.loading
|
|
125
|
-
* @param props.animation
|
|
126
|
-
* @param props.showLegend
|
|
127
|
-
* @param props.
|
|
128
|
-
* @param props.
|
|
129
|
-
* @param props.
|
|
130
|
-
* @param props.
|
|
131
|
-
* @param props.
|
|
132
|
-
* @param props.
|
|
133
|
-
* @param props.legendInteractive - Whether legend items are interactive (clickable to toggle series visibility)
|
|
134
|
-
* @param props.gap - Spacing between legend and chart content
|
|
135
|
-
* @param props.children - Child components for composition API
|
|
136
|
-
* @param props.className - Additional CSS class name
|
|
137
|
-
* @param props.style - Custom styling for the chart container
|
|
113
|
+
* @param props - Component props
|
|
114
|
+
* @param props.data - Array of leaderboard entries to display
|
|
115
|
+
* @param props.chartId - Optional unique identifier for the chart
|
|
116
|
+
* @param props.width - Optional width of the chart container in pixels
|
|
117
|
+
* @param props.height - Optional height of the chart container in pixels
|
|
118
|
+
* @param props.withComparison - Whether to show comparison data
|
|
119
|
+
* @param props.withOverlayLabel - Whether to overlay the label on top of the bar
|
|
120
|
+
* @param props.primaryColor - Primary color for current period bars
|
|
121
|
+
* @param props.secondaryColor - Secondary color for comparison period bars
|
|
122
|
+
* @param props.valueFormatter - Custom formatter for values
|
|
123
|
+
* @param props.deltaFormatter - Custom formatter for delta values
|
|
124
|
+
* @param props.loading - Whether the chart is in loading state
|
|
125
|
+
* @param props.animation - Whether the chart should animate on load
|
|
126
|
+
* @param props.showLegend - Whether to show legend
|
|
127
|
+
* @param props.legend - Legend configuration (orientation, position, alignment, shape, shapeStyles, interactive)
|
|
128
|
+
* @param props.legendLabels - Custom labels for legend items
|
|
129
|
+
* @param props.gap - Spacing between legend and chart content
|
|
130
|
+
* @param props.children - Child components for composition API
|
|
131
|
+
* @param props.className - Additional CSS class name
|
|
132
|
+
* @param props.style - Custom styling for the chart container
|
|
138
133
|
* @return JSX element representing the leaderboard chart
|
|
139
134
|
*/
|
|
140
135
|
const LeaderboardChartInternal: FC< LeaderboardChartProps > = ( {
|
|
@@ -151,24 +146,22 @@ const LeaderboardChartInternal: FC< LeaderboardChartProps > = ( {
|
|
|
151
146
|
animation,
|
|
152
147
|
loading = false,
|
|
153
148
|
showLegend = false,
|
|
154
|
-
|
|
155
|
-
legendPosition = 'bottom',
|
|
156
|
-
legendAlignment = 'center',
|
|
157
|
-
legendShape = 'circle',
|
|
158
|
-
legendShapeStyles: legendShapeStylesProp,
|
|
149
|
+
legend = {},
|
|
159
150
|
legendLabels,
|
|
160
|
-
legendInteractive = false,
|
|
161
151
|
gap = 'md',
|
|
162
152
|
className,
|
|
163
153
|
style,
|
|
164
154
|
children,
|
|
165
155
|
} ) => {
|
|
156
|
+
const legendInteractive = legend.interactive ?? false;
|
|
157
|
+
const legendPosition = legend.position ?? 'bottom';
|
|
158
|
+
|
|
166
159
|
const chartId = useChartId( providedChartId );
|
|
167
160
|
const { leaderboardChart: leaderboardChartSettings } = useGlobalChartsTheme();
|
|
168
|
-
const legendShapeStyles = { width: 8, height: 8, ...
|
|
161
|
+
const legendShapeStyles = { width: 8, height: 8, ...legend.shapeStyles };
|
|
169
162
|
|
|
170
163
|
// Process children to extract compound components
|
|
171
|
-
const {
|
|
164
|
+
const { legendChildren, nonLegendChildren } = useChartChildren( children, 'LeaderboardChart' );
|
|
172
165
|
const {
|
|
173
166
|
labelSpacing,
|
|
174
167
|
rowGap,
|
|
@@ -281,8 +274,8 @@ const LeaderboardChartInternal: FC< LeaderboardChartProps > = ( {
|
|
|
281
274
|
? __( 'Loading…', 'jetpack-charts' )
|
|
282
275
|
: __( 'No data available', 'jetpack-charts' ) }
|
|
283
276
|
</div>
|
|
284
|
-
|
|
285
|
-
{
|
|
277
|
+
|
|
278
|
+
{ nonLegendChildren }
|
|
286
279
|
</Stack>
|
|
287
280
|
</SingleChartContext.Provider>
|
|
288
281
|
);
|
|
@@ -290,10 +283,13 @@ const LeaderboardChartInternal: FC< LeaderboardChartProps > = ( {
|
|
|
290
283
|
|
|
291
284
|
const legendElement = showLegend && (
|
|
292
285
|
<Legend
|
|
293
|
-
orientation={
|
|
286
|
+
orientation={ legend.orientation ?? 'horizontal' }
|
|
294
287
|
position={ legendPosition }
|
|
295
|
-
alignment={
|
|
296
|
-
|
|
288
|
+
alignment={ legend.alignment ?? 'center' }
|
|
289
|
+
labelStyles={ legend.labelStyles }
|
|
290
|
+
itemClassName={ legend.itemClassName }
|
|
291
|
+
itemStyles={ legend.itemStyles }
|
|
292
|
+
shape={ legend.shape ?? 'circle' }
|
|
297
293
|
shapeStyles={ legendShapeStyles }
|
|
298
294
|
chartId={ chartId }
|
|
299
295
|
interactive={ legendInteractive }
|
|
@@ -327,6 +323,7 @@ const LeaderboardChartInternal: FC< LeaderboardChartProps > = ( {
|
|
|
327
323
|
} }
|
|
328
324
|
>
|
|
329
325
|
{ legendPosition === 'top' && legendElement }
|
|
326
|
+
{ renderLegendSlot( legendChildren, 'top' ) }
|
|
330
327
|
|
|
331
328
|
<div className={ styles.leaderboardChart__content }>
|
|
332
329
|
{ allSeriesHidden ? (
|
|
@@ -377,9 +374,9 @@ const LeaderboardChartInternal: FC< LeaderboardChartProps > = ( {
|
|
|
377
374
|
</div>
|
|
378
375
|
|
|
379
376
|
{ legendPosition === 'bottom' && legendElement }
|
|
377
|
+
{ renderLegendSlot( legendChildren, 'bottom' ) }
|
|
380
378
|
|
|
381
|
-
{
|
|
382
|
-
{ otherChildren }
|
|
379
|
+
{ nonLegendChildren }
|
|
383
380
|
</Stack>
|
|
384
381
|
</SingleChartContext.Provider>
|
|
385
382
|
);
|
|
@@ -169,8 +169,7 @@ describe( 'LeaderboardChart', () => {
|
|
|
169
169
|
data={ mockData }
|
|
170
170
|
withComparison={ true }
|
|
171
171
|
showLegend={ true }
|
|
172
|
-
|
|
173
|
-
legendShapeStyles={ { width: 10, height: 6 } }
|
|
172
|
+
legend={ { shape: 'rect', shapeStyles: { width: 10, height: 6 } } }
|
|
174
173
|
/>
|
|
175
174
|
);
|
|
176
175
|
|
|
@@ -306,7 +305,7 @@ describe( 'LeaderboardChart', () => {
|
|
|
306
305
|
data={ mockData }
|
|
307
306
|
withComparison={ true }
|
|
308
307
|
showLegend={ true }
|
|
309
|
-
|
|
308
|
+
legend={ { interactive: true } }
|
|
310
309
|
/>
|
|
311
310
|
);
|
|
312
311
|
|
|
@@ -320,7 +319,7 @@ describe( 'LeaderboardChart', () => {
|
|
|
320
319
|
data={ mockData }
|
|
321
320
|
withComparison={ true }
|
|
322
321
|
showLegend={ true }
|
|
323
|
-
|
|
322
|
+
legend={ { interactive: false } }
|
|
324
323
|
/>
|
|
325
324
|
);
|
|
326
325
|
|
|
@@ -335,7 +334,7 @@ describe( 'LeaderboardChart', () => {
|
|
|
335
334
|
data={ mockData }
|
|
336
335
|
withComparison={ true }
|
|
337
336
|
showLegend={ true }
|
|
338
|
-
|
|
337
|
+
legend={ { interactive: true } }
|
|
339
338
|
/>
|
|
340
339
|
);
|
|
341
340
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { BaseChartProps, LeaderboardEntry } from '../../types';
|
|
3
|
-
import type { LegendShapeStyles } from '../../components/legend';
|
|
4
3
|
|
|
5
4
|
export interface LeaderboardChartProps
|
|
6
5
|
extends Pick<
|
|
@@ -8,16 +7,12 @@ export interface LeaderboardChartProps
|
|
|
8
7
|
| 'className'
|
|
9
8
|
| 'data'
|
|
10
9
|
| 'showLegend'
|
|
11
|
-
| '
|
|
12
|
-
| 'legendPosition'
|
|
13
|
-
| 'legendAlignment'
|
|
14
|
-
| 'legendShape'
|
|
10
|
+
| 'legend'
|
|
15
11
|
| 'chartId'
|
|
16
12
|
| 'width'
|
|
17
13
|
| 'height'
|
|
18
14
|
| 'size'
|
|
19
15
|
| 'gap'
|
|
20
|
-
| 'legendInteractive'
|
|
21
16
|
| 'animation'
|
|
22
17
|
> {
|
|
23
18
|
/**
|
|
@@ -62,11 +57,6 @@ export interface LeaderboardChartProps
|
|
|
62
57
|
'--a8c--charts--leaderboard--bar--border-radius'?: string;
|
|
63
58
|
};
|
|
64
59
|
|
|
65
|
-
/**
|
|
66
|
-
* Styles for legend shapes (width, height, margin).
|
|
67
|
-
*/
|
|
68
|
-
legendShapeStyles?: LegendShapeStyles;
|
|
69
|
-
|
|
70
60
|
/**
|
|
71
61
|
* Custom labels for legend items
|
|
72
62
|
*/
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
useChartDataTransform,
|
|
16
16
|
useChartMargin,
|
|
17
17
|
useElementSize,
|
|
18
|
-
useHasLegendChild,
|
|
19
18
|
usePrefersReducedMotion,
|
|
20
19
|
} from '../../hooks';
|
|
21
20
|
import {
|
|
@@ -27,6 +26,7 @@ import {
|
|
|
27
26
|
useGlobalChartsTheme,
|
|
28
27
|
} from '../../providers';
|
|
29
28
|
import { attachSubComponents } from '../../utils';
|
|
29
|
+
import { useChartChildren, renderLegendSlot } from '../private/chart-composition';
|
|
30
30
|
import { DefaultGlyph } from '../private/default-glyph';
|
|
31
31
|
import { SingleChartContext, type SingleChartRef } from '../private/single-chart-context';
|
|
32
32
|
import { withResponsive } from '../private/with-responsive';
|
|
@@ -256,15 +256,9 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
|
|
|
256
256
|
withTooltips = true,
|
|
257
257
|
withTooltipCrosshairs,
|
|
258
258
|
showLegend = false,
|
|
259
|
-
|
|
260
|
-
legendAlignment = 'center',
|
|
261
|
-
legendPosition = 'bottom',
|
|
262
|
-
legendMaxWidth,
|
|
263
|
-
legendTextOverflow = 'wrap',
|
|
264
|
-
legendItemClassName,
|
|
259
|
+
legend = {},
|
|
265
260
|
renderGlyph = defaultRenderGlyph,
|
|
266
261
|
glyphStyle = {},
|
|
267
|
-
legendShape = 'line',
|
|
268
262
|
withLegendGlyph = false,
|
|
269
263
|
withGradientFill = false,
|
|
270
264
|
smoothing = true,
|
|
@@ -272,7 +266,6 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
|
|
|
272
266
|
renderTooltip = renderDefaultTooltip,
|
|
273
267
|
withStartGlyphs = false,
|
|
274
268
|
withEndGlyphs = false,
|
|
275
|
-
legendInteractive = false,
|
|
276
269
|
animation,
|
|
277
270
|
options = {},
|
|
278
271
|
onPointerDown = undefined,
|
|
@@ -285,6 +278,10 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
|
|
|
285
278
|
},
|
|
286
279
|
ref
|
|
287
280
|
) => {
|
|
281
|
+
const legendInteractive = legend.interactive ?? false;
|
|
282
|
+
const legendShape = legend.shape ?? 'line';
|
|
283
|
+
const legendPosition = legend.position ?? 'bottom';
|
|
284
|
+
|
|
288
285
|
const providerTheme = useGlobalChartsTheme();
|
|
289
286
|
const theme = useXYChartTheme( data );
|
|
290
287
|
const chartId = useChartId( providedChartId );
|
|
@@ -294,8 +291,9 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
|
|
|
294
291
|
const [ isNavigating, setIsNavigating ] = useState( false );
|
|
295
292
|
const internalChartRef = useRef< SingleChartRef >( null );
|
|
296
293
|
|
|
297
|
-
//
|
|
298
|
-
const
|
|
294
|
+
// Process children for composition API (Legend, etc.)
|
|
295
|
+
const { legendChildren, nonLegendChildren } = useChartChildren( children, 'LineChart' );
|
|
296
|
+
const hasLegendChild = legendChildren.length > 0;
|
|
299
297
|
|
|
300
298
|
// Use the measured SVG wrapper height, falling back to the passed height if provided.
|
|
301
299
|
// When there's a legend (via prop or composition), we must wait for measurement because
|
|
@@ -454,11 +452,13 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
|
|
|
454
452
|
|
|
455
453
|
const legendElement = showLegend && (
|
|
456
454
|
<Legend
|
|
457
|
-
orientation={
|
|
458
|
-
alignment={
|
|
455
|
+
orientation={ legend.orientation ?? 'horizontal' }
|
|
456
|
+
alignment={ legend.alignment ?? 'center' }
|
|
459
457
|
position={ legendPosition }
|
|
460
|
-
labelStyles={
|
|
461
|
-
itemClassName={
|
|
458
|
+
labelStyles={ legend.labelStyles }
|
|
459
|
+
itemClassName={ legend.itemClassName }
|
|
460
|
+
itemStyles={ legend.itemStyles }
|
|
461
|
+
shapeStyles={ legend.shapeStyles }
|
|
462
462
|
className={ styles[ 'line-chart__legend' ] }
|
|
463
463
|
shape={ legendShape }
|
|
464
464
|
chartId={ chartId }
|
|
@@ -492,6 +492,7 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
|
|
|
492
492
|
} }
|
|
493
493
|
>
|
|
494
494
|
{ legendPosition === 'top' && legendElement }
|
|
495
|
+
{ renderLegendSlot( legendChildren, 'top' ) }
|
|
495
496
|
|
|
496
497
|
<div
|
|
497
498
|
className={ styles[ 'line-chart__svg-wrapper' ] }
|
|
@@ -654,8 +655,9 @@ const LineChartInternal = forwardRef< SingleChartRef, LineChartProps >(
|
|
|
654
655
|
</div>
|
|
655
656
|
|
|
656
657
|
{ legendPosition === 'bottom' && legendElement }
|
|
658
|
+
{ renderLegendSlot( legendChildren, 'bottom' ) }
|
|
657
659
|
|
|
658
|
-
{
|
|
660
|
+
{ nonLegendChildren }
|
|
659
661
|
</Stack>
|
|
660
662
|
</SingleChartContext.Provider>
|
|
661
663
|
);
|
|
@@ -53,13 +53,15 @@ describe( 'LineChart', () => {
|
|
|
53
53
|
],
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
const renderWithTheme = ( props = {}, themeName = 'default' ) => {
|
|
56
|
+
const renderWithTheme = ( props = {}, themeName = 'default', children = undefined ) => {
|
|
57
57
|
const theme = THEME_MAP[ themeName ];
|
|
58
58
|
|
|
59
59
|
return render(
|
|
60
60
|
<GlobalChartsProvider theme={ theme }>
|
|
61
61
|
{ /* @ts-expect-error TODO Fix the missing props */ }
|
|
62
|
-
<LineChart { ...defaultProps } { ...props }
|
|
62
|
+
<LineChart { ...defaultProps } { ...props }>
|
|
63
|
+
{ children }
|
|
64
|
+
</LineChart>
|
|
63
65
|
</GlobalChartsProvider>
|
|
64
66
|
);
|
|
65
67
|
};
|
|
@@ -130,36 +132,56 @@ describe( 'LineChart', () => {
|
|
|
130
132
|
} );
|
|
131
133
|
|
|
132
134
|
describe( 'Legend', () => {
|
|
135
|
+
const multiSeriesData = [
|
|
136
|
+
{
|
|
137
|
+
label: 'Series A',
|
|
138
|
+
data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
label: 'Series B',
|
|
142
|
+
data: [ { date: new Date( '2024-01-01' ), value: 20, label: 'Jan 1' } ],
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
|
|
133
146
|
test( 'shows legend when showLegend is true', () => {
|
|
134
|
-
renderWithTheme( {
|
|
135
|
-
showLegend: true,
|
|
136
|
-
data: [
|
|
137
|
-
{
|
|
138
|
-
label: 'Series A',
|
|
139
|
-
data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
label: 'Series B',
|
|
143
|
-
data: [ { date: new Date( '2024-01-01' ), value: 20, label: 'Jan 1' } ],
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
} );
|
|
147
|
+
renderWithTheme( { showLegend: true, data: multiSeriesData } );
|
|
147
148
|
expect( screen.getByText( 'Series A' ) ).toBeInTheDocument();
|
|
148
149
|
expect( screen.getByText( 'Series B' ) ).toBeInTheDocument();
|
|
149
150
|
} );
|
|
150
151
|
|
|
151
152
|
test( 'hides legend when showLegend is false', () => {
|
|
152
|
-
renderWithTheme( {
|
|
153
|
-
showLegend: false,
|
|
154
|
-
data: [
|
|
155
|
-
{
|
|
156
|
-
label: 'Series A',
|
|
157
|
-
data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
} );
|
|
153
|
+
renderWithTheme( { showLegend: false, data: multiSeriesData } );
|
|
161
154
|
expect( screen.queryByText( 'Series A' ) ).not.toBeInTheDocument();
|
|
162
155
|
} );
|
|
156
|
+
|
|
157
|
+
test( 'renders composition legend as child component', () => {
|
|
158
|
+
renderWithTheme( { data: multiSeriesData }, 'default', <LineChart.Legend /> );
|
|
159
|
+
|
|
160
|
+
expect( screen.getAllByTestId( 'legend-item' ) ).toHaveLength( 2 );
|
|
161
|
+
expect( screen.getByText( 'Series A' ) ).toBeInTheDocument();
|
|
162
|
+
expect( screen.getByText( 'Series B' ) ).toBeInTheDocument();
|
|
163
|
+
} );
|
|
164
|
+
|
|
165
|
+
test( 'renders composition legend regardless of showLegend value', () => {
|
|
166
|
+
renderWithTheme(
|
|
167
|
+
{ data: multiSeriesData, showLegend: false },
|
|
168
|
+
'default',
|
|
169
|
+
<LineChart.Legend />
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
expect( screen.getAllByTestId( 'legend-item' ) ).toHaveLength( 2 );
|
|
173
|
+
} );
|
|
174
|
+
|
|
175
|
+
test( 'renders composition legend in top position', () => {
|
|
176
|
+
renderWithTheme( { data: multiSeriesData }, 'default', <LineChart.Legend position="top" /> );
|
|
177
|
+
|
|
178
|
+
// Legend should appear before the chart content in DOM order
|
|
179
|
+
expect( screen.getAllByTestId( 'legend-item' ) ).toHaveLength( 2 );
|
|
180
|
+
const html = document.body.innerHTML;
|
|
181
|
+
expect( html.indexOf( 'data-testid="legend-horizontal"' ) ).toBeLessThan(
|
|
182
|
+
html.indexOf( 'role="grid"' )
|
|
183
|
+
);
|
|
184
|
+
} );
|
|
163
185
|
} );
|
|
164
186
|
|
|
165
187
|
describe( 'Gradient Fill', () => {
|
|
@@ -1178,7 +1200,7 @@ describe( 'LineChart', () => {
|
|
|
1178
1200
|
{ ...defaultProps }
|
|
1179
1201
|
withGradientFill={ false }
|
|
1180
1202
|
showLegend={ true }
|
|
1181
|
-
|
|
1203
|
+
legend={ { interactive: true } }
|
|
1182
1204
|
chartId="test-interactive-chart"
|
|
1183
1205
|
/>
|
|
1184
1206
|
</GlobalChartsProvider>
|
|
@@ -1200,7 +1222,7 @@ describe( 'LineChart', () => {
|
|
|
1200
1222
|
{ ...defaultProps }
|
|
1201
1223
|
withGradientFill={ false }
|
|
1202
1224
|
showLegend={ true }
|
|
1203
|
-
|
|
1225
|
+
legend={ { interactive: false } }
|
|
1204
1226
|
chartId="test-non-interactive-chart"
|
|
1205
1227
|
/>
|
|
1206
1228
|
</GlobalChartsProvider>
|
|
@@ -1218,7 +1240,7 @@ describe( 'LineChart', () => {
|
|
|
1218
1240
|
{ ...defaultProps }
|
|
1219
1241
|
withGradientFill={ false }
|
|
1220
1242
|
showLegend={ true }
|
|
1221
|
-
|
|
1243
|
+
legend={ { interactive: true } }
|
|
1222
1244
|
// No chartId provided
|
|
1223
1245
|
/>
|
|
1224
1246
|
</GlobalChartsProvider>
|
|
@@ -18,7 +18,12 @@ import {
|
|
|
18
18
|
} from '../../providers';
|
|
19
19
|
import { attachSubComponents } from '../../utils';
|
|
20
20
|
import { getStringWidth } from '../../visx/text';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
ChartSVG,
|
|
23
|
+
ChartHTML,
|
|
24
|
+
useChartChildren,
|
|
25
|
+
renderLegendSlot,
|
|
26
|
+
} from '../private/chart-composition';
|
|
22
27
|
import { RadialWipeAnimation } from '../private/radial-wipe-animation/';
|
|
23
28
|
import { SingleChartContext } from '../private/single-chart-context';
|
|
24
29
|
import { withResponsive, ResponsiveConfig } from '../private/with-responsive';
|
|
@@ -93,13 +98,6 @@ export interface PieChartProps extends BaseChartProps< DataPointPercentage[] > {
|
|
|
93
98
|
*/
|
|
94
99
|
legendValueDisplay?: LegendValueDisplay;
|
|
95
100
|
|
|
96
|
-
/**
|
|
97
|
-
* Enable interactive legend items that can toggle segment visibility.
|
|
98
|
-
* Requires chartId and GlobalChartsProvider.
|
|
99
|
-
* When segments are hidden, percentages are recalculated so visible segments total 100%.
|
|
100
|
-
*/
|
|
101
|
-
legendInteractive?: boolean;
|
|
102
|
-
|
|
103
101
|
/**
|
|
104
102
|
* Use the children prop to render additional elements on the chart.
|
|
105
103
|
*/
|
|
@@ -169,13 +167,7 @@ const PieChartInternal = ( {
|
|
|
169
167
|
withTooltips = false,
|
|
170
168
|
className,
|
|
171
169
|
showLegend = false,
|
|
172
|
-
|
|
173
|
-
legendPosition = 'bottom',
|
|
174
|
-
legendAlignment = 'center',
|
|
175
|
-
legendMaxWidth,
|
|
176
|
-
legendTextOverflow = 'wrap',
|
|
177
|
-
legendItemClassName,
|
|
178
|
-
legendShape = 'circle',
|
|
170
|
+
legend = {},
|
|
179
171
|
width: propWidth,
|
|
180
172
|
height: propHeight,
|
|
181
173
|
size,
|
|
@@ -186,13 +178,15 @@ const PieChartInternal = ( {
|
|
|
186
178
|
cornerScale = 0,
|
|
187
179
|
showLabels = true,
|
|
188
180
|
legendValueDisplay = 'percentage',
|
|
189
|
-
legendInteractive = false,
|
|
190
181
|
children = null,
|
|
191
182
|
tooltipOffsetX = 0,
|
|
192
183
|
tooltipOffsetY = -15,
|
|
193
184
|
renderTooltip = renderDefaultPieTooltip,
|
|
194
185
|
gap = 'md',
|
|
195
186
|
}: PieChartProps ) => {
|
|
187
|
+
const legendInteractive = legend.interactive ?? false;
|
|
188
|
+
const legendPosition = legend.position ?? 'bottom';
|
|
189
|
+
|
|
196
190
|
const providerTheme = useGlobalChartsTheme();
|
|
197
191
|
const chartId = useChartId( providedChartId );
|
|
198
192
|
const [ svgWrapperRef, svgWrapperWidth, svgWrapperHeight ] = useElementSize< HTMLDivElement >();
|
|
@@ -236,7 +230,10 @@ const PieChartInternal = ( {
|
|
|
236
230
|
const { isValid, message } = validateData( data );
|
|
237
231
|
|
|
238
232
|
// Process children to extract compound components
|
|
239
|
-
const { svgChildren, htmlChildren, otherChildren } = useChartChildren(
|
|
233
|
+
const { svgChildren, htmlChildren, legendChildren, otherChildren } = useChartChildren(
|
|
234
|
+
children,
|
|
235
|
+
'PieChart'
|
|
236
|
+
);
|
|
240
237
|
|
|
241
238
|
// Memoize metadata to prevent unnecessary re-registration
|
|
242
239
|
const chartMetadata = useMemo(
|
|
@@ -314,12 +311,14 @@ const PieChartInternal = ( {
|
|
|
314
311
|
|
|
315
312
|
const legendElement = showLegend && (
|
|
316
313
|
<Legend
|
|
317
|
-
orientation={
|
|
314
|
+
orientation={ legend.orientation ?? 'horizontal' }
|
|
318
315
|
position={ legendPosition }
|
|
319
|
-
alignment={
|
|
320
|
-
labelStyles={
|
|
321
|
-
itemClassName={
|
|
322
|
-
|
|
316
|
+
alignment={ legend.alignment ?? 'center' }
|
|
317
|
+
labelStyles={ legend.labelStyles }
|
|
318
|
+
itemClassName={ legend.itemClassName }
|
|
319
|
+
itemStyles={ legend.itemStyles }
|
|
320
|
+
shapeStyles={ legend.shapeStyles }
|
|
321
|
+
shape={ legend.shape ?? 'circle' }
|
|
323
322
|
chartId={ chartId }
|
|
324
323
|
interactive={ legendInteractive }
|
|
325
324
|
/>
|
|
@@ -350,6 +349,7 @@ const PieChartInternal = ( {
|
|
|
350
349
|
} }
|
|
351
350
|
>
|
|
352
351
|
{ legendPosition === 'top' && legendElement }
|
|
352
|
+
{ renderLegendSlot( legendChildren, 'top' ) }
|
|
353
353
|
|
|
354
354
|
<div className={ styles[ 'pie-chart__svg-wrapper' ] } ref={ svgWrapperRef }>
|
|
355
355
|
<svg
|
|
@@ -482,6 +482,7 @@ const PieChartInternal = ( {
|
|
|
482
482
|
</div>
|
|
483
483
|
|
|
484
484
|
{ legendPosition === 'bottom' && legendElement }
|
|
485
|
+
{ renderLegendSlot( legendChildren, 'bottom' ) }
|
|
485
486
|
|
|
486
487
|
{ withTooltips && tooltipOpen && tooltipData && (
|
|
487
488
|
<TooltipInPortal top={ tooltipTop || 0 } left={ tooltipLeft || 0 }>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { render, screen } from '@testing-library/react';
|
|
2
2
|
import { Group } from '@visx/group';
|
|
3
3
|
import '@testing-library/jest-dom';
|
|
4
|
+
import { GlobalChartsProvider } from '../../../providers';
|
|
4
5
|
import { PieChartUnresponsive as PieChart } from '../index';
|
|
5
6
|
|
|
6
7
|
describe( 'PieChart Composition API', () => {
|
|
@@ -10,6 +11,16 @@ describe( 'PieChart Composition API', () => {
|
|
|
10
11
|
{ label: 'C', value: 30, percentage: 30 },
|
|
11
12
|
];
|
|
12
13
|
|
|
14
|
+
const renderWithChildren = ( props = {}, children = undefined ) => {
|
|
15
|
+
return render(
|
|
16
|
+
<GlobalChartsProvider>
|
|
17
|
+
<PieChart data={ mockData } size={ 400 } { ...props }>
|
|
18
|
+
{ children }
|
|
19
|
+
</PieChart>
|
|
20
|
+
</GlobalChartsProvider>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
13
24
|
describe( 'Compound Components', () => {
|
|
14
25
|
it( 'renders PieChart.SVG children inside the SVG element', () => {
|
|
15
26
|
render(
|
|
@@ -148,4 +159,34 @@ describe( 'PieChart Composition API', () => {
|
|
|
148
159
|
expect( svg!.contains( newHtml ) ).toBe( false );
|
|
149
160
|
} );
|
|
150
161
|
} );
|
|
162
|
+
|
|
163
|
+
describe( 'Composition Legend', () => {
|
|
164
|
+
test( 'renders composition legend as child component', () => {
|
|
165
|
+
renderWithChildren( {}, <PieChart.Legend /> );
|
|
166
|
+
|
|
167
|
+
const legendItems = screen.getAllByTestId( 'legend-item' );
|
|
168
|
+
expect( legendItems ).toHaveLength( 3 );
|
|
169
|
+
expect( legendItems[ 0 ] ).toHaveTextContent( 'A' );
|
|
170
|
+
expect( legendItems[ 1 ] ).toHaveTextContent( 'B' );
|
|
171
|
+
expect( legendItems[ 2 ] ).toHaveTextContent( 'C' );
|
|
172
|
+
} );
|
|
173
|
+
|
|
174
|
+
test( 'renders composition legend regardless of showLegend value', () => {
|
|
175
|
+
renderWithChildren( { showLegend: false }, <PieChart.Legend /> );
|
|
176
|
+
|
|
177
|
+
expect( screen.getAllByTestId( 'legend-item' ) ).toHaveLength( 3 );
|
|
178
|
+
} );
|
|
179
|
+
|
|
180
|
+
test( 'renders composition legend in top position', () => {
|
|
181
|
+
renderWithChildren( {}, <PieChart.Legend position="top" /> );
|
|
182
|
+
|
|
183
|
+
expect( screen.getAllByTestId( 'legend-item' ) ).toHaveLength( 3 );
|
|
184
|
+
|
|
185
|
+
// Legend should appear before the chart SVG in DOM order
|
|
186
|
+
const html = document.body.innerHTML;
|
|
187
|
+
expect( html.indexOf( 'data-testid="legend-horizontal"' ) ).toBeLessThan(
|
|
188
|
+
html.indexOf( 'data-testid="pie-segment"' )
|
|
189
|
+
);
|
|
190
|
+
} );
|
|
191
|
+
} );
|
|
151
192
|
} );
|