@automattic/charts 0.56.7 → 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/AGENTS.md +28 -98
- package/CHANGELOG.md +30 -0
- package/dist/charts/bar-chart/index.cjs +7 -6
- 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 -5
- package/dist/charts/bar-list-chart/index.cjs +8 -7
- 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 -6
- package/dist/charts/conversion-funnel-chart/index.cjs +5 -6
- package/dist/charts/conversion-funnel-chart/index.cjs.map +1 -1
- 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 -5
- 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 +20 -33
- 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 -6
- 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 -5
- package/dist/charts/pie-chart/index.cjs +7 -7
- 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 -6
- package/dist/charts/pie-semi-circle-chart/index.cjs +7 -7
- 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 -6
- package/dist/charts/sparkline/index.cjs +8 -7
- 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 -6
- package/dist/{chunk-RFSHE3HL.js → chunk-2I67QUIV.js} +84 -431
- package/dist/chunk-2I67QUIV.js.map +1 -0
- package/dist/{chunk-OMS5QIJN.js → chunk-2ICEEQOC.js} +31 -25
- package/dist/chunk-2ICEEQOC.js.map +1 -0
- package/dist/{chunk-GWBS65VC.js → chunk-4B7BL2DD.js} +3 -3
- package/dist/{chunk-7FDQGBY7.js → chunk-4OXMTKAL.js} +24 -24
- package/dist/chunk-4OXMTKAL.js.map +1 -0
- package/dist/{chunk-SSFFCBCF.js → chunk-B6NLZFRW.js} +32 -26
- package/dist/chunk-B6NLZFRW.js.map +1 -0
- package/dist/{chunk-3EXJP67N.cjs → chunk-BBAUQOW6.cjs} +9 -9
- package/dist/{chunk-3EXJP67N.cjs.map → chunk-BBAUQOW6.cjs.map} +1 -1
- package/dist/{chunk-NQJE2CC7.cjs → chunk-CMMHCTBX.cjs} +45 -45
- package/dist/chunk-CMMHCTBX.cjs.map +1 -0
- package/dist/{chunk-O2JIANHK.cjs → chunk-CPPXJATQ.cjs} +51 -45
- package/dist/chunk-CPPXJATQ.cjs.map +1 -0
- package/dist/{chunk-MDRCAGKZ.js → chunk-DKU775VC.js} +3 -3
- package/dist/{chunk-BXFD7JIG.cjs → chunk-GRA7Y2ZG.cjs} +46 -46
- package/dist/chunk-GRA7Y2ZG.cjs.map +1 -0
- package/dist/{chunk-TE63Y5PX.js → chunk-JJIMABHT.js} +10 -3
- package/dist/chunk-JJIMABHT.js.map +1 -0
- package/dist/{chunk-KHQPN77E.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-VPAEBI2F.js → chunk-LTFH7SEG.js} +24 -24
- package/dist/chunk-LTFH7SEG.js.map +1 -0
- package/dist/{chunk-E62LCBGD.js → chunk-MUNOKLLE.js} +3 -3
- package/dist/{chunk-ZVGEDXDP.cjs → chunk-MXGLYWVP.cjs} +10 -3
- package/dist/chunk-MXGLYWVP.cjs.map +1 -0
- package/dist/{chunk-55ZCOYDF.cjs → chunk-OYC34VTO.cjs} +252 -827
- package/dist/chunk-OYC34VTO.cjs.map +1 -0
- package/dist/{chunk-CAFJRZPZ.cjs → chunk-PQL5I3F6.cjs} +17 -17
- package/dist/{chunk-CAFJRZPZ.cjs.map → chunk-PQL5I3F6.cjs.map} +1 -1
- package/dist/{chunk-UFRBUT2D.cjs → chunk-REZTQ4PH.cjs} +87 -24
- 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-XD2HV7M5.js → chunk-UTYVIOWZ.js} +226 -801
- package/dist/chunk-UTYVIOWZ.js.map +1 -0
- package/dist/{chunk-YAXY5L7I.cjs → chunk-W2LDIX26.cjs} +5 -5
- package/dist/{chunk-YAXY5L7I.cjs.map → chunk-W2LDIX26.cjs.map} +1 -1
- package/dist/{chunk-K6TGILHX.cjs → chunk-WSG64BVN.cjs} +6 -6
- package/dist/{chunk-K6TGILHX.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-YDVHT7GS.cjs → chunk-WYK7EL5R.cjs} +100 -447
- package/dist/chunk-WYK7EL5R.cjs.map +1 -0
- package/dist/{chunk-X7JL2NYJ.cjs → chunk-XC4KHJYX.cjs} +51 -45
- 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-IS5YYLTV.js → chunk-YAFQVVDI.js} +85 -22
- 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 +9 -13
- package/dist/hooks/index.d.ts +9 -13
- package/dist/hooks/index.js +2 -4
- package/dist/index.cjs +18 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +20 -33
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +17 -16
- package/dist/{leaderboard-chart-COtgamhe.d.cts → leaderboard-chart-BSbg0ufV.d.cts} +3 -11
- package/dist/{leaderboard-chart-BSgEw_Um.d.ts → leaderboard-chart-odEYxxEC.d.ts} +3 -11
- package/dist/{legend-C9ahiwOt.d.cts → legend-DFkosEvC.d.cts} +1 -1
- package/dist/{legend-jjMmhSg3.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-CVR5rmIs.d.cts → themes-D0qc5JaW.d.cts} +2 -2
- package/dist/{themes-DQzmaSze.d.ts → themes-itO4Ht5g.d.ts} +2 -2
- package/dist/{types-BBwg4Evw.d.cts → types-B5f6XQ7Q.d.cts} +1 -1
- package/dist/{types-DQNnq5Fr.d.ts → types-BsHooDbM.d.ts} +1 -1
- package/dist/{types-C05PdDJa.d.cts → types-BuSrRM4p.d.ts} +15 -23
- package/dist/{types-CzdN7rUe.d.cts → types-ChOUI9-N.d.cts} +90 -46
- package/dist/{types-CzdN7rUe.d.ts → types-ChOUI9-N.d.ts} +90 -46
- package/dist/{types-C05PdDJa.d.ts → types-Dfw9VOKI.d.cts} +15 -23
- 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 +10 -8
- package/src/charts/bar-chart/bar-chart.tsx +19 -19
- package/src/charts/bar-chart/test/bar-chart.test.tsx +78 -31
- package/src/charts/conversion-funnel-chart/test/conversion-funnel-chart.test.tsx +2 -2
- package/src/charts/leaderboard-chart/hooks/use-leaderboard-legend-items.ts +0 -2
- package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +9 -10
- package/src/charts/leaderboard-chart/leaderboard-chart.tsx +124 -102
- package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +61 -33
- package/src/charts/leaderboard-chart/test/use-leaderboard-legend-items.test.tsx +2 -5
- package/src/charts/leaderboard-chart/types.ts +2 -15
- package/src/charts/line-chart/line-chart.tsx +18 -17
- 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 -23
- 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 -24
- 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/private/base-legend.module.scss +19 -37
- package/src/components/legend/private/base-legend.tsx +32 -24
- package/src/components/legend/test/legend.test.tsx +148 -52
- package/src/components/legend/types.ts +23 -24
- package/src/hooks/index.ts +0 -1
- package/src/hooks/test/use-zero-value-display.test.tsx +206 -0
- package/src/hooks/use-zero-value-display.ts +52 -23
- package/src/providers/chart-context/test/chart-context.test.tsx +12 -6
- package/src/providers/chart-context/themes.ts +6 -4
- package/src/types.ts +93 -44
- package/src/utils/date-parsing.ts +10 -1
- package/src/utils/get-styles.ts +1 -1
- package/src/utils/test/date-parsing.test.ts +12 -0
- package/src/utils/test/get-styles.test.ts +12 -10
- package/src/utils/test/resolve-css-var.test.ts +2 -2
- package/tsup.config.ts +1 -1
- package/dist/chunk-55ZCOYDF.cjs.map +0 -1
- package/dist/chunk-6CCZL2JJ.js.map +0 -1
- package/dist/chunk-7FDQGBY7.js.map +0 -1
- package/dist/chunk-BXFD7JIG.cjs.map +0 -1
- package/dist/chunk-IS5YYLTV.js.map +0 -1
- package/dist/chunk-KNIMXN6Z.js +0 -51
- package/dist/chunk-KNIMXN6Z.js.map +0 -1
- package/dist/chunk-NQJE2CC7.cjs.map +0 -1
- package/dist/chunk-O2JIANHK.cjs.map +0 -1
- package/dist/chunk-OMS5QIJN.js.map +0 -1
- package/dist/chunk-RCY6XLGU.cjs.map +0 -1
- package/dist/chunk-RFSHE3HL.js.map +0 -1
- package/dist/chunk-SSFFCBCF.js.map +0 -1
- package/dist/chunk-SUDERBUA.cjs +0 -51
- package/dist/chunk-SUDERBUA.cjs.map +0 -1
- package/dist/chunk-TE63Y5PX.js.map +0 -1
- package/dist/chunk-UFRBUT2D.cjs.map +0 -1
- package/dist/chunk-VPAEBI2F.js.map +0 -1
- package/dist/chunk-X7JL2NYJ.cjs.map +0 -1
- package/dist/chunk-XD2HV7M5.js.map +0 -1
- package/dist/chunk-YDVHT7GS.cjs.map +0 -1
- package/dist/chunk-ZVGEDXDP.cjs.map +0 -1
- package/src/hooks/use-has-legend-child.ts +0 -22
- /package/dist/{chunk-GWBS65VC.js.map → chunk-4B7BL2DD.js.map} +0 -0
- /package/dist/{chunk-MDRCAGKZ.js.map → chunk-DKU775VC.js.map} +0 -0
- /package/dist/{chunk-KHQPN77E.js.map → chunk-KJHWXOCZ.js.map} +0 -0
- /package/dist/{chunk-E62LCBGD.js.map → chunk-MUNOKLLE.js.map} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { renderHook } from '@testing-library/react';
|
|
2
2
|
import { Group } from '@visx/group';
|
|
3
|
+
import { Legend } from '../../../../components/legend';
|
|
3
4
|
import { ChartSVG, ChartHTML } from '../index';
|
|
4
5
|
import { useChartChildren } from '../use-chart-children';
|
|
5
6
|
|
|
@@ -22,6 +23,7 @@ describe( 'useChartChildren', () => {
|
|
|
22
23
|
|
|
23
24
|
expect( result.current.svgChildren ).toHaveLength( 1 );
|
|
24
25
|
expect( result.current.htmlChildren ).toHaveLength( 0 );
|
|
26
|
+
expect( result.current.legendChildren ).toHaveLength( 0 );
|
|
25
27
|
expect( result.current.otherChildren ).toHaveLength( 0 );
|
|
26
28
|
} );
|
|
27
29
|
|
|
@@ -58,6 +60,7 @@ describe( 'useChartChildren', () => {
|
|
|
58
60
|
|
|
59
61
|
expect( result.current.svgChildren ).toHaveLength( 1 );
|
|
60
62
|
expect( result.current.htmlChildren ).toHaveLength( 1 );
|
|
63
|
+
expect( result.current.legendChildren ).toHaveLength( 0 );
|
|
61
64
|
expect( result.current.otherChildren ).toHaveLength( 0 );
|
|
62
65
|
} );
|
|
63
66
|
|
|
@@ -112,6 +115,7 @@ describe( 'useChartChildren', () => {
|
|
|
112
115
|
|
|
113
116
|
expect( result.current.svgChildren ).toHaveLength( 0 );
|
|
114
117
|
expect( result.current.htmlChildren ).toHaveLength( 0 );
|
|
118
|
+
expect( result.current.legendChildren ).toHaveLength( 0 );
|
|
115
119
|
expect( result.current.otherChildren ).toHaveLength( 0 );
|
|
116
120
|
} );
|
|
117
121
|
|
|
@@ -128,4 +132,91 @@ describe( 'useChartChildren', () => {
|
|
|
128
132
|
|
|
129
133
|
expect( result.current.svgChildren ).toHaveLength( 3 );
|
|
130
134
|
} );
|
|
135
|
+
|
|
136
|
+
it( 'should extract Legend children to legendChildren with default position bottom', () => {
|
|
137
|
+
const children = <Legend />;
|
|
138
|
+
|
|
139
|
+
const { result } = renderHook( () => useChartChildren( children, 'TestChart' ) );
|
|
140
|
+
|
|
141
|
+
expect( result.current.legendChildren ).toHaveLength( 1 );
|
|
142
|
+
expect( result.current.legendChildren[ 0 ].position ).toBe( 'bottom' );
|
|
143
|
+
expect( result.current.otherChildren ).toHaveLength( 0 );
|
|
144
|
+
} );
|
|
145
|
+
|
|
146
|
+
it( 'should extract Legend children with position top', () => {
|
|
147
|
+
const children = <Legend position="top" />;
|
|
148
|
+
|
|
149
|
+
const { result } = renderHook( () => useChartChildren( children, 'TestChart' ) );
|
|
150
|
+
|
|
151
|
+
expect( result.current.legendChildren ).toHaveLength( 1 );
|
|
152
|
+
expect( result.current.legendChildren[ 0 ].position ).toBe( 'top' );
|
|
153
|
+
expect( result.current.otherChildren ).toHaveLength( 0 );
|
|
154
|
+
} );
|
|
155
|
+
|
|
156
|
+
it( 'should default to bottom for invalid position values', () => {
|
|
157
|
+
// @ts-expect-error -- testing invalid runtime value
|
|
158
|
+
const children = <Legend position="left" />;
|
|
159
|
+
|
|
160
|
+
const { result } = renderHook( () => useChartChildren( children, 'TestChart' ) );
|
|
161
|
+
|
|
162
|
+
expect( result.current.legendChildren ).toHaveLength( 1 );
|
|
163
|
+
expect( result.current.legendChildren[ 0 ].position ).toBe( 'bottom' );
|
|
164
|
+
} );
|
|
165
|
+
|
|
166
|
+
it( 'should exclude Legend children from nonLegendChildren', () => {
|
|
167
|
+
const children = [
|
|
168
|
+
<Legend key="legend" position="top" />,
|
|
169
|
+
<div key="other">Other Content</div>,
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
const { result } = renderHook( () => useChartChildren( children, 'TestChart' ) );
|
|
173
|
+
|
|
174
|
+
expect( result.current.legendChildren ).toHaveLength( 1 );
|
|
175
|
+
expect( result.current.nonLegendChildren ).toHaveLength( 1 );
|
|
176
|
+
} );
|
|
177
|
+
|
|
178
|
+
it( 'should preserve original child order in nonLegendChildren', () => {
|
|
179
|
+
const children = [
|
|
180
|
+
<div key="first">First</div>,
|
|
181
|
+
<Legend key="legend" position="top" />,
|
|
182
|
+
<Group key="group">
|
|
183
|
+
<text>SVG</text>
|
|
184
|
+
</Group>,
|
|
185
|
+
<div key="last">Last</div>,
|
|
186
|
+
];
|
|
187
|
+
|
|
188
|
+
const { result } = renderHook( () => useChartChildren( children, 'TestChart' ) );
|
|
189
|
+
|
|
190
|
+
expect( result.current.nonLegendChildren ).toHaveLength( 3 );
|
|
191
|
+
// Verify order matches original (minus the Legend)
|
|
192
|
+
expect( ( result.current.nonLegendChildren[ 0 ] as React.ReactElement ).key ).toBe( 'first' );
|
|
193
|
+
expect( ( result.current.nonLegendChildren[ 1 ] as React.ReactElement ).key ).toBe( 'group' );
|
|
194
|
+
expect( ( result.current.nonLegendChildren[ 2 ] as React.ReactElement ).key ).toBe( 'last' );
|
|
195
|
+
} );
|
|
196
|
+
|
|
197
|
+
it( 'should return empty nonLegendChildren when all children are Legends', () => {
|
|
198
|
+
const children = [
|
|
199
|
+
<Legend key="top" position="top" />,
|
|
200
|
+
<Legend key="bottom" position="bottom" />,
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
const { result } = renderHook( () => useChartChildren( children, 'TestChart' ) );
|
|
204
|
+
|
|
205
|
+
expect( result.current.legendChildren ).toHaveLength( 2 );
|
|
206
|
+
expect( result.current.nonLegendChildren ).toHaveLength( 0 );
|
|
207
|
+
} );
|
|
208
|
+
|
|
209
|
+
it( 'should extract multiple Legend children by position', () => {
|
|
210
|
+
const children = [
|
|
211
|
+
<Legend key="top" position="top" />,
|
|
212
|
+
<Legend key="bottom" position="bottom" />,
|
|
213
|
+
];
|
|
214
|
+
|
|
215
|
+
const { result } = renderHook( () => useChartChildren( children, 'TestChart' ) );
|
|
216
|
+
|
|
217
|
+
expect( result.current.legendChildren ).toHaveLength( 2 );
|
|
218
|
+
expect( result.current.legendChildren[ 0 ].position ).toBe( 'top' );
|
|
219
|
+
expect( result.current.legendChildren[ 1 ].position ).toBe( 'bottom' );
|
|
220
|
+
expect( result.current.otherChildren ).toHaveLength( 0 );
|
|
221
|
+
} );
|
|
131
222
|
} );
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { Group } from '@visx/group';
|
|
2
2
|
import { useMemo, Children, isValidElement } from 'react';
|
|
3
|
-
import
|
|
3
|
+
import { Legend } from '../../../components/legend';
|
|
4
|
+
import type { LegendPosition } from '../../../types';
|
|
5
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
export type LegendChild = {
|
|
8
|
+
element: ReactElement;
|
|
9
|
+
position: LegendPosition;
|
|
10
|
+
};
|
|
4
11
|
|
|
5
12
|
interface ChartChildren {
|
|
6
13
|
svgChildren: ReactNode[];
|
|
7
14
|
htmlChildren: ReactNode[];
|
|
15
|
+
legendChildren: LegendChild[];
|
|
8
16
|
otherChildren: ReactNode[];
|
|
17
|
+
/** All children except Legend, in original order. */
|
|
18
|
+
nonLegendChildren: ReactNode[];
|
|
9
19
|
}
|
|
10
20
|
|
|
11
21
|
/**
|
|
@@ -21,10 +31,23 @@ export function useChartChildren( children: ReactNode, chartType: string ): Char
|
|
|
21
31
|
return useMemo( () => {
|
|
22
32
|
const svg: ReactNode[] = [];
|
|
23
33
|
const html: ReactNode[] = [];
|
|
34
|
+
const legend: LegendChild[] = [];
|
|
24
35
|
const other: ReactNode[] = [];
|
|
36
|
+
const nonLegend: ReactNode[] = [];
|
|
25
37
|
|
|
26
38
|
Children.forEach( children, child => {
|
|
27
39
|
if ( isValidElement( child ) ) {
|
|
40
|
+
// Extract Legend children for position-based slot rendering
|
|
41
|
+
if ( child.type === Legend ) {
|
|
42
|
+
const rawPosition = child.props?.position;
|
|
43
|
+
const position =
|
|
44
|
+
rawPosition === 'top' || rawPosition === 'bottom' ? rawPosition : 'bottom';
|
|
45
|
+
|
|
46
|
+
legend.push( { element: child as ReactElement, position } );
|
|
47
|
+
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
28
51
|
// Check displayName for compound components
|
|
29
52
|
const childType = child.type as { displayName?: string };
|
|
30
53
|
const displayName = childType?.displayName;
|
|
@@ -51,8 +74,17 @@ export function useChartChildren( children: ReactNode, chartType: string ): Char
|
|
|
51
74
|
other.push( child );
|
|
52
75
|
}
|
|
53
76
|
}
|
|
77
|
+
|
|
78
|
+
// Preserve original order of all non-Legend children
|
|
79
|
+
nonLegend.push( child );
|
|
54
80
|
} );
|
|
55
81
|
|
|
56
|
-
return {
|
|
82
|
+
return {
|
|
83
|
+
svgChildren: svg,
|
|
84
|
+
htmlChildren: html,
|
|
85
|
+
legendChildren: legend,
|
|
86
|
+
otherChildren: other,
|
|
87
|
+
nonLegendChildren: nonLegend,
|
|
88
|
+
};
|
|
57
89
|
}, [ children, chartType ] );
|
|
58
90
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
.legend {
|
|
2
|
+
align-self: stretch;
|
|
2
3
|
|
|
3
4
|
&--horizontal {
|
|
4
5
|
display: flex;
|
|
@@ -11,52 +12,33 @@
|
|
|
11
12
|
display: flex;
|
|
12
13
|
flex-direction: column;
|
|
13
14
|
gap: 8px;
|
|
14
|
-
|
|
15
|
-
&.legend--alignment-start {
|
|
16
|
-
align-items: flex-start;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
&.legend--alignment-center {
|
|
20
|
-
align-items: center;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
&.legend--alignment-end {
|
|
24
|
-
align-items: flex-end;
|
|
25
|
-
}
|
|
26
15
|
}
|
|
27
16
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
&.legend--alignment-start {
|
|
33
|
-
justify-content: flex-start;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
&.legend--alignment-center {
|
|
37
|
-
justify-content: center;
|
|
38
|
-
}
|
|
17
|
+
&--alignment-start {
|
|
18
|
+
justify-content: flex-start;
|
|
19
|
+
}
|
|
39
20
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
21
|
+
&--alignment-center {
|
|
22
|
+
justify-content: center;
|
|
43
23
|
}
|
|
44
24
|
|
|
45
|
-
&--
|
|
46
|
-
|
|
25
|
+
&--alignment-end {
|
|
26
|
+
justify-content: flex-end;
|
|
27
|
+
}
|
|
47
28
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
29
|
+
// Vertical legends align on the cross-axis instead
|
|
30
|
+
&--vertical.legend--alignment-start {
|
|
31
|
+
align-items: flex-start;
|
|
32
|
+
}
|
|
51
33
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
&--vertical.legend--alignment-center {
|
|
35
|
+
align-items: center;
|
|
36
|
+
}
|
|
55
37
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
38
|
+
&--vertical.legend--alignment-end {
|
|
39
|
+
align-items: flex-end;
|
|
59
40
|
}
|
|
41
|
+
|
|
60
42
|
}
|
|
61
43
|
|
|
62
44
|
.legend-item {
|
|
@@ -67,32 +67,37 @@ export const BaseLegend: ForwardRefExoticComponent<
|
|
|
67
67
|
items,
|
|
68
68
|
className,
|
|
69
69
|
orientation = 'horizontal',
|
|
70
|
-
position = 'bottom',
|
|
71
70
|
alignment = 'center',
|
|
72
|
-
maxWidth,
|
|
73
|
-
textOverflow = 'wrap',
|
|
74
71
|
shape = 'rect',
|
|
75
72
|
fill = valueOrIdentityString,
|
|
76
73
|
size = valueOrIdentityString,
|
|
77
74
|
labelFormat = valueOrIdentity,
|
|
78
75
|
labelTransform = labelTransformFactory,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
labelMargin = '0 4px',
|
|
85
|
-
itemMargin = '0',
|
|
86
|
-
itemDirection = 'row',
|
|
87
|
-
legendLabelProps,
|
|
88
|
-
legendItemClassName,
|
|
76
|
+
itemStyles,
|
|
77
|
+
itemClassName,
|
|
78
|
+
labelStyles,
|
|
79
|
+
labelClassName,
|
|
80
|
+
shapeStyles,
|
|
89
81
|
render,
|
|
90
82
|
interactive = false,
|
|
91
83
|
chartId,
|
|
92
|
-
...legendItemProps
|
|
93
84
|
},
|
|
94
85
|
ref
|
|
95
86
|
) => {
|
|
87
|
+
const { margin: itemMargin = '0', flexDirection: itemDirection = 'row' } = itemStyles ?? {};
|
|
88
|
+
const {
|
|
89
|
+
justifyContent: labelJustifyContent = 'flex-start',
|
|
90
|
+
flex: labelFlex = '0 0 auto',
|
|
91
|
+
margin: labelMargin = '0 4px',
|
|
92
|
+
maxWidth,
|
|
93
|
+
textOverflow = 'wrap',
|
|
94
|
+
} = labelStyles ?? {};
|
|
95
|
+
const {
|
|
96
|
+
width: shapeWidth = 16,
|
|
97
|
+
height: shapeHeight = 16,
|
|
98
|
+
margin: shapeMargin = '2px 4px 2px 0',
|
|
99
|
+
} = shapeStyles ?? {};
|
|
100
|
+
|
|
96
101
|
const theme = useGlobalChartsTheme();
|
|
97
102
|
const context = useContext( GlobalChartsContext );
|
|
98
103
|
|
|
@@ -171,18 +176,18 @@ export const BaseLegend: ForwardRefExoticComponent<
|
|
|
171
176
|
styles.legend,
|
|
172
177
|
styles[ `legend--${ orientation }` ],
|
|
173
178
|
styles[ `legend--alignment-${ alignment }` ],
|
|
174
|
-
styles[ `legend--position-${ position }` ],
|
|
175
179
|
className
|
|
176
180
|
) }
|
|
177
181
|
style={ {
|
|
178
182
|
flexDirection: orientationToFlexDirection[ orientation ],
|
|
179
|
-
...theme.
|
|
183
|
+
...theme.legend?.containerStyles,
|
|
180
184
|
} }
|
|
181
185
|
>
|
|
182
186
|
{ labels.map( ( label, i ) => {
|
|
183
187
|
const visible = isSeriesVisible( label.text );
|
|
184
188
|
const handleClick = createClickHandler( label.text );
|
|
185
189
|
const handleKeyDown = createKeyDownHandler( label.text );
|
|
190
|
+
const matchedItem = items[ i ];
|
|
186
191
|
|
|
187
192
|
return (
|
|
188
193
|
<LegendItem
|
|
@@ -191,7 +196,7 @@ export const BaseLegend: ForwardRefExoticComponent<
|
|
|
191
196
|
styles[ 'legend-item' ],
|
|
192
197
|
interactive && styles[ 'legend-item--interactive' ],
|
|
193
198
|
! visible && styles[ 'legend-item--inactive' ],
|
|
194
|
-
|
|
199
|
+
itemClassName
|
|
195
200
|
) }
|
|
196
201
|
data-testid="legend-item"
|
|
197
202
|
key={ `legend-${ label.text }-${ i }` }
|
|
@@ -211,7 +216,6 @@ export const BaseLegend: ForwardRefExoticComponent<
|
|
|
211
216
|
? `${ label.text }: ${ visible ? 'visible' : 'hidden' }. Toggle visibility.`
|
|
212
217
|
: undefined
|
|
213
218
|
}
|
|
214
|
-
{ ...legendItemProps }
|
|
215
219
|
>
|
|
216
220
|
{ items[ i ]?.renderGlyph ? (
|
|
217
221
|
<svg
|
|
@@ -246,24 +250,28 @@ export const BaseLegend: ForwardRefExoticComponent<
|
|
|
246
250
|
/>
|
|
247
251
|
) }
|
|
248
252
|
<LegendLabel
|
|
249
|
-
|
|
253
|
+
data-testid="legend-label"
|
|
254
|
+
className={ clsx(
|
|
255
|
+
'visx-legend-label',
|
|
256
|
+
styles[ 'legend-item-label' ],
|
|
257
|
+
labelClassName
|
|
258
|
+
) }
|
|
250
259
|
style={ {
|
|
251
|
-
justifyContent:
|
|
260
|
+
justifyContent: labelJustifyContent,
|
|
252
261
|
flex: labelFlex,
|
|
253
262
|
margin: labelMargin,
|
|
254
|
-
...theme.
|
|
263
|
+
...theme.legend?.labelStyles,
|
|
255
264
|
} }
|
|
256
|
-
{ ...legendLabelProps }
|
|
257
265
|
>
|
|
258
266
|
<LegendText
|
|
259
267
|
text={ label.text }
|
|
260
268
|
textOverflow={ textOverflow }
|
|
261
269
|
maxWidth={ maxWidth }
|
|
262
270
|
/>
|
|
263
|
-
{
|
|
271
|
+
{ matchedItem?.value != null && matchedItem.value !== '' && (
|
|
264
272
|
<span className={ styles[ 'legend-item-value' ] }>
|
|
265
273
|
{ '\u00A0' }
|
|
266
|
-
{
|
|
274
|
+
{ matchedItem.value }
|
|
267
275
|
</span>
|
|
268
276
|
) }
|
|
269
277
|
</LegendLabel>
|
|
@@ -46,12 +46,12 @@ describe( 'BaseLegend', () => {
|
|
|
46
46
|
expect( legendItems ).toHaveLength( 0 );
|
|
47
47
|
} );
|
|
48
48
|
|
|
49
|
-
test( 'applies
|
|
49
|
+
test( 'applies itemClassName to legend items', () => {
|
|
50
50
|
render(
|
|
51
51
|
<BaseLegend
|
|
52
52
|
items={ defaultItems }
|
|
53
53
|
orientation="horizontal"
|
|
54
|
-
|
|
54
|
+
itemClassName="custom-legend-item"
|
|
55
55
|
/>
|
|
56
56
|
);
|
|
57
57
|
const legendItems = screen.getAllByTestId( 'legend-item' );
|
|
@@ -60,16 +60,65 @@ describe( 'BaseLegend', () => {
|
|
|
60
60
|
} );
|
|
61
61
|
} );
|
|
62
62
|
|
|
63
|
+
test( 'applies labelClassName to legend labels', () => {
|
|
64
|
+
render(
|
|
65
|
+
<BaseLegend
|
|
66
|
+
items={ defaultItems }
|
|
67
|
+
orientation="horizontal"
|
|
68
|
+
labelClassName="custom-legend-label"
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
const labels = screen.getAllByTestId( 'legend-label' );
|
|
72
|
+
labels.forEach( label => {
|
|
73
|
+
expect( label ).toHaveClass( 'custom-legend-label' );
|
|
74
|
+
} );
|
|
75
|
+
} );
|
|
76
|
+
|
|
63
77
|
test( 'handles missing values', () => {
|
|
64
78
|
const itemsWithoutValues = [
|
|
65
|
-
{ label: 'Item 1', color: '#ff0000'
|
|
66
|
-
{ label: 'Item 2', color: '#00ff00'
|
|
79
|
+
{ label: 'Item 1', color: '#ff0000' },
|
|
80
|
+
{ label: 'Item 2', color: '#00ff00' },
|
|
67
81
|
];
|
|
68
82
|
render( <BaseLegend items={ itemsWithoutValues } orientation="horizontal" /> );
|
|
69
83
|
expect( screen.getByText( 'Item 1' ) ).toBeInTheDocument();
|
|
70
84
|
expect( screen.getByText( 'Item 2' ) ).toBeInTheDocument();
|
|
71
85
|
} );
|
|
72
86
|
|
|
87
|
+
test( 'does not render value span for empty string values', () => {
|
|
88
|
+
const itemsWithEmptyValues = [
|
|
89
|
+
{ label: 'Item 1', color: '#ff0000', value: '' },
|
|
90
|
+
{ label: 'Item 2', color: '#00ff00', value: '' },
|
|
91
|
+
];
|
|
92
|
+
render( <BaseLegend items={ itemsWithEmptyValues } orientation="horizontal" /> );
|
|
93
|
+
expect( screen.getByText( 'Item 1' ) ).toBeInTheDocument();
|
|
94
|
+
expect( screen.getByText( 'Item 2' ) ).toBeInTheDocument();
|
|
95
|
+
expect( screen.queryByText( '\u00A0' ) ).not.toBeInTheDocument();
|
|
96
|
+
} );
|
|
97
|
+
|
|
98
|
+
test( 'renders numeric value of 0 without hiding it', () => {
|
|
99
|
+
const itemsWithZeroValue = [
|
|
100
|
+
{ label: 'Item 1', color: '#ff0000', value: 0 },
|
|
101
|
+
{ label: 'Item 2', color: '#00ff00', value: '0%' },
|
|
102
|
+
];
|
|
103
|
+
render( <BaseLegend items={ itemsWithZeroValue } orientation="horizontal" /> );
|
|
104
|
+
expect( screen.getByText( '0' ) ).toBeInTheDocument();
|
|
105
|
+
expect( screen.getByText( '0%' ) ).toBeInTheDocument();
|
|
106
|
+
} );
|
|
107
|
+
|
|
108
|
+
test( 'renders each value next to its corresponding label by index', () => {
|
|
109
|
+
const itemsWithDistinctValues = [
|
|
110
|
+
{ label: 'Alpha', value: '100', color: '#ff0000' },
|
|
111
|
+
{ label: 'Beta', value: '200', color: '#00ff00' },
|
|
112
|
+
{ label: 'Gamma', value: '300', color: '#0000ff' },
|
|
113
|
+
];
|
|
114
|
+
render( <BaseLegend items={ itemsWithDistinctValues } orientation="horizontal" /> );
|
|
115
|
+
const legendItems = screen.getAllByTestId( 'legend-item' );
|
|
116
|
+
expect( legendItems ).toHaveLength( 3 );
|
|
117
|
+
expect( legendItems[ 0 ] ).toHaveTextContent( /Alpha.*100/ );
|
|
118
|
+
expect( legendItems[ 1 ] ).toHaveTextContent( /Beta.*200/ );
|
|
119
|
+
expect( legendItems[ 2 ] ).toHaveTextContent( /Gamma.*300/ );
|
|
120
|
+
} );
|
|
121
|
+
|
|
73
122
|
test( 'applies custom className', () => {
|
|
74
123
|
render(
|
|
75
124
|
<BaseLegend items={ defaultItems } className="custom-legend" orientation="horizontal" />
|
|
@@ -106,108 +155,155 @@ describe( 'BaseLegend', () => {
|
|
|
106
155
|
{ label: 'Another Long Label for Testing', value: '30%', color: '#00ff00' },
|
|
107
156
|
];
|
|
108
157
|
|
|
109
|
-
test( '
|
|
110
|
-
render(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
158
|
+
test( 'applies maxWidth and minWidth styles to label text', () => {
|
|
159
|
+
render(
|
|
160
|
+
<BaseLegend
|
|
161
|
+
items={ longLabelItems }
|
|
162
|
+
labelStyles={ { maxWidth: '150px' } }
|
|
163
|
+
orientation="horizontal"
|
|
164
|
+
/>
|
|
165
|
+
);
|
|
166
|
+
const labels = screen.getAllByText( /Long Label/ );
|
|
167
|
+
labels.forEach( label => {
|
|
168
|
+
expect( label ).toHaveStyle( { maxWidth: '150px', minWidth: 0 } );
|
|
169
|
+
} );
|
|
115
170
|
} );
|
|
116
171
|
|
|
117
|
-
test( '
|
|
118
|
-
render(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
172
|
+
test( 'supports different CSS units for maxWidth', () => {
|
|
173
|
+
render(
|
|
174
|
+
<BaseLegend
|
|
175
|
+
items={ longLabelItems }
|
|
176
|
+
labelStyles={ { maxWidth: '10rem' } }
|
|
177
|
+
orientation="horizontal"
|
|
178
|
+
/>
|
|
179
|
+
);
|
|
180
|
+
const labels = screen.getAllByText( /Long Label/ );
|
|
181
|
+
labels.forEach( label => {
|
|
182
|
+
expect( label ).toHaveStyle( { maxWidth: '10rem' } );
|
|
183
|
+
} );
|
|
122
184
|
} );
|
|
123
185
|
|
|
124
|
-
test( '
|
|
186
|
+
test( 'does not apply maxWidth styles when omitted', () => {
|
|
125
187
|
const { rerender } = render(
|
|
126
188
|
<BaseLegend items={ longLabelItems } orientation="horizontal" />
|
|
127
189
|
);
|
|
128
190
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
191
|
+
let labels = screen.getAllByText( /Long Label/ );
|
|
192
|
+
labels.forEach( label => {
|
|
193
|
+
expect( label ).not.toHaveStyle( { maxWidth: '150px' } );
|
|
194
|
+
} );
|
|
132
195
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
196
|
+
rerender(
|
|
197
|
+
<BaseLegend
|
|
198
|
+
items={ longLabelItems }
|
|
199
|
+
labelStyles={ { maxWidth: '150px' } }
|
|
200
|
+
orientation="horizontal"
|
|
201
|
+
/>
|
|
202
|
+
);
|
|
203
|
+
labels = screen.getAllByText( /Long Label/ );
|
|
204
|
+
labels.forEach( label => {
|
|
205
|
+
expect( label ).toHaveStyle( { maxWidth: '150px', minWidth: 0 } );
|
|
206
|
+
} );
|
|
137
207
|
} );
|
|
138
208
|
|
|
139
|
-
test( '
|
|
140
|
-
// Test ellipsis behavior - should render without errors
|
|
209
|
+
test( 'applies maxWidth styles for both textOverflow modes', () => {
|
|
141
210
|
const { rerender } = render(
|
|
142
211
|
<BaseLegend
|
|
143
212
|
items={ longLabelItems }
|
|
144
|
-
maxWidth
|
|
145
|
-
textOverflow="ellipsis"
|
|
213
|
+
labelStyles={ { maxWidth: '150px', textOverflow: 'ellipsis' } }
|
|
146
214
|
orientation="horizontal"
|
|
147
215
|
/>
|
|
148
216
|
);
|
|
149
217
|
let labels = screen.getAllByText( /Long Label/ );
|
|
150
|
-
|
|
218
|
+
labels.forEach( label => {
|
|
219
|
+
expect( label ).toHaveStyle( { maxWidth: '150px', minWidth: 0 } );
|
|
220
|
+
} );
|
|
151
221
|
|
|
152
|
-
// Test wrap behavior - should render without errors
|
|
153
222
|
rerender(
|
|
154
223
|
<BaseLegend
|
|
155
224
|
items={ longLabelItems }
|
|
156
|
-
maxWidth
|
|
157
|
-
textOverflow="wrap"
|
|
225
|
+
labelStyles={ { maxWidth: '150px', textOverflow: 'wrap' } }
|
|
158
226
|
orientation="horizontal"
|
|
159
227
|
/>
|
|
160
228
|
);
|
|
161
229
|
labels = screen.getAllByText( /Long Label/ );
|
|
162
|
-
|
|
230
|
+
labels.forEach( label => {
|
|
231
|
+
expect( label ).toHaveStyle( { maxWidth: '150px', minWidth: 0 } );
|
|
232
|
+
} );
|
|
163
233
|
} );
|
|
164
234
|
|
|
165
|
-
test( '
|
|
166
|
-
// Render with ellipsis overflow
|
|
235
|
+
test( 'applies maxWidth=0px correctly', () => {
|
|
167
236
|
render(
|
|
168
237
|
<BaseLegend
|
|
169
238
|
items={ longLabelItems }
|
|
170
|
-
maxWidth
|
|
171
|
-
textOverflow="ellipsis"
|
|
239
|
+
labelStyles={ { maxWidth: '0px', textOverflow: 'ellipsis' } }
|
|
172
240
|
orientation="horizontal"
|
|
173
241
|
/>
|
|
174
242
|
);
|
|
175
|
-
|
|
176
|
-
// Verify the text is rendered
|
|
177
243
|
const labels = screen.getAllByText( /Long Label/ );
|
|
178
|
-
|
|
244
|
+
labels.forEach( label => {
|
|
245
|
+
expect( label ).toHaveStyle( { maxWidth: '0px', minWidth: 0 } );
|
|
246
|
+
} );
|
|
179
247
|
} );
|
|
180
248
|
|
|
181
|
-
test( '
|
|
182
|
-
// Render with wrap overflow
|
|
249
|
+
test( 'applies legend-item-text--ellipsis class when textOverflow is ellipsis and maxWidth is set', () => {
|
|
183
250
|
render(
|
|
184
251
|
<BaseLegend
|
|
185
252
|
items={ longLabelItems }
|
|
186
|
-
maxWidth
|
|
187
|
-
textOverflow="wrap"
|
|
253
|
+
labelStyles={ { maxWidth: '150px', textOverflow: 'ellipsis' } }
|
|
188
254
|
orientation="horizontal"
|
|
189
255
|
/>
|
|
190
256
|
);
|
|
257
|
+
const labels = screen.getAllByText( /Long Label/ );
|
|
258
|
+
labels.forEach( label => {
|
|
259
|
+
expect( label ).toHaveClass( 'legend-item-text--ellipsis' );
|
|
260
|
+
expect( label ).not.toHaveClass( 'legend-item-text--wrap' );
|
|
261
|
+
} );
|
|
262
|
+
} );
|
|
191
263
|
|
|
192
|
-
|
|
264
|
+
test( 'applies legend-item-text--wrap class when textOverflow is wrap and maxWidth is set', () => {
|
|
265
|
+
render(
|
|
266
|
+
<BaseLegend
|
|
267
|
+
items={ longLabelItems }
|
|
268
|
+
labelStyles={ { maxWidth: '150px', textOverflow: 'wrap' } }
|
|
269
|
+
orientation="horizontal"
|
|
270
|
+
/>
|
|
271
|
+
);
|
|
193
272
|
const labels = screen.getAllByText( /Long Label/ );
|
|
194
|
-
|
|
273
|
+
labels.forEach( label => {
|
|
274
|
+
expect( label ).toHaveClass( 'legend-item-text--wrap' );
|
|
275
|
+
expect( label ).not.toHaveClass( 'legend-item-text--ellipsis' );
|
|
276
|
+
} );
|
|
195
277
|
} );
|
|
196
278
|
|
|
197
|
-
test( '
|
|
198
|
-
// maxWidth={0} should apply 0-pixel constraint (not be treated as "no constraint")
|
|
279
|
+
test( 'does not apply overflow class when maxWidth is not set', () => {
|
|
199
280
|
render(
|
|
200
281
|
<BaseLegend
|
|
201
282
|
items={ longLabelItems }
|
|
202
|
-
|
|
203
|
-
textOverflow="ellipsis"
|
|
283
|
+
labelStyles={ { textOverflow: 'ellipsis' } }
|
|
204
284
|
orientation="horizontal"
|
|
205
285
|
/>
|
|
206
286
|
);
|
|
287
|
+
const labels = screen.getAllByText( /Long Label/ );
|
|
288
|
+
labels.forEach( label => {
|
|
289
|
+
expect( label ).not.toHaveClass( 'legend-item-text--ellipsis' );
|
|
290
|
+
expect( label ).not.toHaveClass( 'legend-item-text--wrap' );
|
|
291
|
+
} );
|
|
292
|
+
} );
|
|
207
293
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
294
|
+
test( 'does not apply overflow class when maxWidth is not set and textOverflow is wrap', () => {
|
|
295
|
+
render(
|
|
296
|
+
<BaseLegend
|
|
297
|
+
items={ longLabelItems }
|
|
298
|
+
labelStyles={ { textOverflow: 'wrap' } }
|
|
299
|
+
orientation="horizontal"
|
|
300
|
+
/>
|
|
301
|
+
);
|
|
302
|
+
const labels = screen.getAllByText( /Long Label/ );
|
|
303
|
+
labels.forEach( label => {
|
|
304
|
+
expect( label ).not.toHaveClass( 'legend-item-text--wrap' );
|
|
305
|
+
expect( label ).not.toHaveClass( 'legend-item-text--ellipsis' );
|
|
306
|
+
} );
|
|
211
307
|
} );
|
|
212
308
|
} );
|
|
213
309
|
|