@@ -52,6 +52,7 @@ import {
52
52
createStringYAxis ,
53
53
formatDate ,
54
54
getNextGradient ,
55
+ areArraysEqual ,
55
56
} from '../../utilities/index' ;
56
57
import { IChart } from '../../types/index' ;
57
58
@@ -73,6 +74,7 @@ export interface IVerticalBarChartState extends IBasestate {
73
74
hoverXValue ?: string | number | null ;
74
75
callOutAccessibilityData ?: IAccessibilityProps ;
75
76
calloutLegend : string ;
77
+ selectedLegends : string [ ] ;
76
78
}
77
79
78
80
type ColorScale = ( _p ?: number ) => string ;
@@ -118,8 +120,8 @@ export class VerticalBarChartBase
118
120
dataForHoverCard : 0 ,
119
121
isCalloutVisible : false ,
120
122
refSelected : null ,
121
- selectedLegend : props . legendProps ?. selectedLegend ?? '' ,
122
- activeLegend : '' ,
123
+ selectedLegends : props . legendProps ?. selectedLegends || [ ] ,
124
+ activeLegend : undefined ,
123
125
xCalloutValue : '' ,
124
126
yCalloutValue : '' ,
125
127
activeXdataPoint : null ,
@@ -141,9 +143,9 @@ export class VerticalBarChartBase
141
143
}
142
144
143
145
public componentDidUpdate ( prevProps : IVerticalBarChartProps ) : void {
144
- if ( prevProps . legendProps ?. selectedLegend !== this . props . legendProps ?. selectedLegend ) {
146
+ if ( ! areArraysEqual ( prevProps . legendProps ?. selectedLegends , this . props . legendProps ?. selectedLegends ) ) {
145
147
this . setState ( {
146
- selectedLegend : this . props . legendProps ?. selectedLegend ?? '' ,
148
+ selectedLegends : this . props . legendProps ?. selectedLegends || [ ] ,
147
149
} ) ;
148
150
}
149
151
}
@@ -199,7 +201,8 @@ export class VerticalBarChartBase
199
201
createYAxis = { createNumericYAxis }
200
202
calloutProps = { calloutProps }
201
203
tickParams = { tickParams }
202
- { ...( this . _isHavingLine && this . _noLegendHighlighted ( ) && { isCalloutForStack : true } ) }
204
+ { ...( this . _isHavingLine &&
205
+ ( this . _noLegendHighlighted ( ) || this . _getHighlightedLegend ( ) . length > 1 ) && { isCalloutForStack : true } ) }
203
206
legendBars = { legendBars }
204
207
datasetForXAxisDomain = { this . _xAxisLabels }
205
208
barwidth = { this . _barWidth }
@@ -404,11 +407,11 @@ export class VerticalBarChartBase
404
407
xAxisPoint : string | number | Date ,
405
408
legend : string ,
406
409
) : { visibility : CircleVisbility ; radius : number } => {
407
- const { selectedLegend , activeXdataPoint } = this . state ;
408
- if ( selectedLegend !== '' ) {
409
- if ( xAxisPoint === activeXdataPoint && selectedLegend === legend ) {
410
+ const { activeXdataPoint } = this . state ;
411
+ if ( ! this . _noLegendHighlighted ( ) ) {
412
+ if ( xAxisPoint === activeXdataPoint && this . _legendHighlighted ( legend ) ) {
410
413
return { visibility : CircleVisbility . show , radius : 8 } ;
411
- } else if ( selectedLegend === legend ) {
414
+ } else if ( this . _legendHighlighted ( legend ) ) {
412
415
// Don't hide the circle to keep it focusable. For more information,
413
416
// see https://fuzzbomb.github.io/accessibility-demos/visually-hidden-focus-test.html
414
417
return { visibility : CircleVisbility . show , radius : 0.3 } ;
@@ -539,7 +542,11 @@ export class VerticalBarChartBase
539
542
: this . _createColors ( ) ( 1 ) ;
540
543
541
544
// there might be no y value of the line for the hovered bar. so we need to check this condition
542
- if ( this . _isHavingLine && selectedPoint [ 0 ] . lineData ?. y !== undefined ) {
545
+ if (
546
+ this . _isHavingLine &&
547
+ selectedPoint [ 0 ] . lineData ?. y !== undefined &&
548
+ ( this . _legendHighlighted ( lineLegendText ) || this . _noLegendHighlighted ( ) )
549
+ ) {
543
550
// callout data for the line
544
551
YValueHover . push ( {
545
552
legend : lineLegendText ,
@@ -549,18 +556,20 @@ export class VerticalBarChartBase
549
556
yAxisCalloutData : selectedPoint [ 0 ] . lineData ?. yAxisCalloutData ,
550
557
} ) ;
551
558
}
552
- // callout data for the bar
553
- YValueHover . push ( {
554
- legend : selectedPoint [ 0 ] . legend ,
555
- y : selectedPoint [ 0 ] . y ,
556
- color : enableGradient
557
- ? useSingleColor
558
- ? getNextGradient ( 0 , 0 ) [ 0 ]
559
- : selectedPoint [ 0 ] . gradient ?. [ 0 ] || getNextGradient ( pointIndex , 0 ) [ 0 ]
560
- : calloutColor ,
561
- data : selectedPoint [ 0 ] . yAxisCalloutData ,
562
- yAxisCalloutData : selectedPoint [ 0 ] . yAxisCalloutData ,
563
- } ) ;
559
+ if ( this . _legendHighlighted ( selectedPoint [ 0 ] . legend ) || this . _noLegendHighlighted ( ) ) {
560
+ // callout data for the bar
561
+ YValueHover . push ( {
562
+ legend : selectedPoint [ 0 ] . legend ,
563
+ y : selectedPoint [ 0 ] . y ,
564
+ color : enableGradient
565
+ ? useSingleColor
566
+ ? getNextGradient ( 0 , 0 ) [ 0 ]
567
+ : selectedPoint [ 0 ] . gradient ?. [ 0 ] || getNextGradient ( pointIndex , 0 ) [ 0 ]
568
+ : calloutColor ,
569
+ data : selectedPoint [ 0 ] . yAxisCalloutData ,
570
+ yAxisCalloutData : selectedPoint [ 0 ] . yAxisCalloutData ,
571
+ } ) ;
572
+ }
564
573
const hoverXValue = point . x instanceof Date ? formatDate ( point . x , this . props . useUTC ) : point . x . toString ( ) ;
565
574
return {
566
575
YValueHover,
@@ -581,7 +590,7 @@ export class VerticalBarChartBase
581
590
this . setState ( {
582
591
refSelected : mouseEvent ,
583
592
/** Show the callout if highlighted bar is hovered and Hide it if unhighlighted bar is hovered */
584
- isCalloutVisible : this . state . selectedLegend === '' || this . state . selectedLegend === point . legend ,
593
+ isCalloutVisible : this . _noLegendHighlighted ( ) || this . _legendHighlighted ( point . legend ) ,
585
594
dataForHoverCard : point . y ,
586
595
calloutLegend : point . legend ! ,
587
596
color : point . color || color ,
@@ -592,7 +601,7 @@ export class VerticalBarChartBase
592
601
yCalloutValue : point . yAxisCalloutData ! ,
593
602
dataPointCalloutProps : point ,
594
603
// Hovering over a bar should highlight corresponding line points only when no legend is selected
595
- activeXdataPoint : this . _noLegendHighlighted ( ) ? point . x : null ,
604
+ activeXdataPoint : this . _noLegendHighlighted ( ) || this . _legendHighlighted ( point . legend ) ? point . x : null ,
596
605
YValueHover,
597
606
hoverXValue,
598
607
callOutAccessibilityData : point . callOutAccessibilityData ,
@@ -621,7 +630,7 @@ export class VerticalBarChartBase
621
630
this . setState ( {
622
631
refSelected : obj . refElement ,
623
632
/** Show the callout if highlighted bar is focused and Hide it if unhighlighted bar is focused */
624
- isCalloutVisible : this . state . selectedLegend === '' || this . state . selectedLegend === point . legend ,
633
+ isCalloutVisible : this . _noLegendHighlighted ( ) || this . _legendHighlighted ( point . legend ) ,
625
634
calloutLegend : point . legend ! ,
626
635
dataForHoverCard : point . y ,
627
636
color : point . color || color ,
@@ -1059,18 +1068,6 @@ export class VerticalBarChartBase
1059
1068
} ) ;
1060
1069
} ;
1061
1070
1062
- private _onLegendClick ( legendTitle : string ) : void {
1063
- if ( this . state . selectedLegend === legendTitle ) {
1064
- this . setState ( {
1065
- selectedLegend : '' ,
1066
- } ) ;
1067
- } else {
1068
- this . setState ( {
1069
- selectedLegend : legendTitle ,
1070
- } ) ;
1071
- }
1072
- }
1073
-
1074
1071
private _onLegendHover ( legendTitle : string ) : void {
1075
1072
this . setState ( {
1076
1073
activeLegend : legendTitle ,
@@ -1079,7 +1076,7 @@ export class VerticalBarChartBase
1079
1076
1080
1077
private _onLegendLeave ( ) : void {
1081
1078
this . setState ( {
1082
- activeLegend : '' ,
1079
+ activeLegend : undefined ,
1083
1080
} ) ;
1084
1081
}
1085
1082
@@ -1106,9 +1103,6 @@ export class VerticalBarChartBase
1106
1103
const legend : ILegend = {
1107
1104
title : legendTitle ,
1108
1105
color,
1109
- action : ( ) => {
1110
- this . _onLegendClick ( legendTitle ) ;
1111
- } ,
1112
1106
hoverAction : ( ) => {
1113
1107
this . _handleChartMouseLeave ( ) ;
1114
1108
this . _onLegendHover ( legendTitle ) ;
@@ -1123,9 +1117,6 @@ export class VerticalBarChartBase
1123
1117
const lineLegend : ILegend = {
1124
1118
title : lineLegendText ,
1125
1119
color : lineLegendColor ,
1126
- action : ( ) => {
1127
- this . _onLegendClick ( lineLegendText ) ;
1128
- } ,
1129
1120
hoverAction : ( ) => {
1130
1121
this . _handleChartMouseLeave ( ) ;
1131
1122
this . _onLegendHover ( lineLegendText ) ;
@@ -1145,11 +1136,27 @@ export class VerticalBarChartBase
1145
1136
focusZonePropsInHoverCard = { this . props . focusZonePropsForLegendsInHoverCard }
1146
1137
overflowText = { this . props . legendsOverflowText }
1147
1138
{ ...this . props . legendProps }
1139
+ onChange = { this . _onLegendSelectionChange . bind ( this ) }
1148
1140
/>
1149
1141
) ;
1150
1142
return legends ;
1151
1143
} ;
1152
1144
1145
+ private _onLegendSelectionChange (
1146
+ selectedLegends : string [ ] ,
1147
+ event : React . MouseEvent < HTMLButtonElement > ,
1148
+ currentLegend ?: ILegend ,
1149
+ ) : void {
1150
+ if ( this . props . legendProps ?. canSelectMultipleLegends ) {
1151
+ this . setState ( { selectedLegends } ) ;
1152
+ } else {
1153
+ this . setState ( { selectedLegends : selectedLegends . slice ( - 1 ) } ) ;
1154
+ }
1155
+ if ( this . props . legendProps ?. onChange ) {
1156
+ this . props . legendProps . onChange ( selectedLegends , event , currentLegend ) ;
1157
+ }
1158
+ }
1159
+
1153
1160
private _getAxisData = ( yAxisData : IAxisData ) => {
1154
1161
if ( yAxisData && yAxisData . yAxisDomainValues . length ) {
1155
1162
const { yAxisDomainValues : domainValue } = yAxisData ;
@@ -1164,20 +1171,25 @@ export class VerticalBarChartBase
1164
1171
* 1. selection: if the user clicks on it
1165
1172
* 2. hovering: if there is no selected legend and the user hovers over it
1166
1173
*/
1167
- private _legendHighlighted = ( legendTitle : string ) => {
1168
- return (
1169
- this . state . selectedLegend === legendTitle ||
1170
- ( this . state . selectedLegend === '' && this . state . activeLegend === legendTitle )
1171
- ) ;
1174
+ private _legendHighlighted = ( legendTitle : string | undefined ) => {
1175
+ return this . _getHighlightedLegend ( ) . includes ( legendTitle ! ) ;
1172
1176
} ;
1173
1177
1174
1178
/**
1175
1179
* This function checks if none of the legends is selected or hovered.
1176
1180
*/
1177
1181
private _noLegendHighlighted = ( ) => {
1178
- return this . state . selectedLegend === '' && this . state . activeLegend === '' ;
1182
+ return this . _getHighlightedLegend ( ) . length === 0 ;
1179
1183
} ;
1180
1184
1185
+ private _getHighlightedLegend ( ) {
1186
+ return this . state . selectedLegends . length > 0
1187
+ ? this . state . selectedLegends
1188
+ : this . state . activeLegend
1189
+ ? [ this . state . activeLegend ]
1190
+ : [ ] ;
1191
+ }
1192
+
1181
1193
private _getAriaLabel = ( point : IVerticalBarChartDataPoint ) : string => {
1182
1194
const xValue = point . xAxisCalloutData
1183
1195
? point . xAxisCalloutData
0 commit comments