diff --git a/packages/charting/src/components/CommonComponents/CartesianChart.base.tsx b/packages/charting/src/components/CommonComponents/CartesianChart.base.tsx index 2d5b0bc57b62aa..8a7335641e6149 100644 --- a/packages/charting/src/components/CommonComponents/CartesianChart.base.tsx +++ b/packages/charting/src/components/CommonComponents/CartesianChart.base.tsx @@ -66,10 +66,10 @@ export class CartesianChartBase extends React.Component; type NumericScale = D3ScaleLinear; type StringScale = D3ScaleLinear; const COMPONENT_NAME = 'VERTICAL STACKED BAR CHART'; -interface IBarRef { - index: number | string; - refElement: SVGGElement; + +interface IRefArrayData { + refElement?: SVGGElement | null; } export interface IVerticalStackedBarChartState extends IBasestate { @@ -50,8 +49,6 @@ export class VerticalStackedBarChartBase extends React.Component< private _barWidth: number; private _calloutId: string; private _classNames: IProcessedStyleSet; - private _refArray: IRefArrayData[]; - private _barRefArray: IBarRef[]; private _colors: string[]; private margins: IMargins; private _isRtl: boolean = getRTL(); @@ -78,8 +75,6 @@ export class VerticalStackedBarChartBase extends React.Component< this._onLegendLeave = this._onLegendLeave.bind(this); this._handleMouseOut = this._handleMouseOut.bind(this); this._calloutId = getId('callout'); - this._refArray = []; - this._barRefArray = []; this._adjustProps(); this._dataset = this._createDataSetLayer(); } @@ -280,14 +275,6 @@ export class VerticalStackedBarChartBase extends React.Component< ); } - private _refCallback(rectElement: SVGRectElement, legendTitle: string, index: number): void { - this._refArray[index] = { index: legendTitle, refElement: rectElement }; - } - - private _barRefCallback = (barElement: SVGGElement, index: number, xAxisPoint: number | string): void => { - this._barRefArray[index] = { index: xAxisPoint, refElement: barElement }; - }; - private _onRectHover( xAxisPoint: string, point: IVSChartDataPoint, @@ -327,44 +314,36 @@ export class VerticalStackedBarChartBase extends React.Component< }); }; - private _onRectFocus(point: IVSChartDataPoint, xAxisPoint: string, color: string, refArrayIndexNumber: number): void { + private _onRectFocus(point: IVSChartDataPoint, xAxisPoint: string, color: string, ref: IRefArrayData): void { if ( this.state.isLegendSelected === false || (this.state.isLegendSelected && this.state.selectedLegendTitle === point.legend) ) { - this._refArray.forEach((obj: IRefArrayData, index: number) => { - if (obj.index === point.legend && refArrayIndexNumber === index) { - this.setState({ - refSelected: obj.refElement, - isCalloutVisible: true, - selectedLegendTitle: point.legend, - dataForHoverCard: point.data, - color: color, - xCalloutValue: point.xAxisCalloutData ? point.xAxisCalloutData : xAxisPoint, - yCalloutValue: point.yAxisCalloutData, - dataPointCalloutProps: point, - }); - } + this.setState({ + refSelected: ref.refElement, + isCalloutVisible: true, + selectedLegendTitle: point.legend, + dataForHoverCard: point.data, + color: color, + xCalloutValue: point.xAxisCalloutData ? point.xAxisCalloutData : xAxisPoint, + yCalloutValue: point.yAxisCalloutData, + dataPointCalloutProps: point, }); } } - private _onStackFocus = (xAxisPoint: string | number): void => { + private _onStackFocus = (xAxisPoint: string | number, groupRef: IRefArrayData): void => { const found = find( this._points, (sinlgePoint: { xAxisPoint: string | number; chartData: IVSChartDataPoint[] }) => sinlgePoint.xAxisPoint === xAxisPoint, ); - this._barRefArray.forEach((obj: IBarRef) => { - if (obj.index === xAxisPoint) { - this.setState({ - refSelected: obj.refElement, - isCalloutVisible: true, - YValueHover: found!.chartData, - hoverXValue: xAxisPoint, - stackCalloutProps: found!, - }); - } + this.setState({ + refSelected: groupRef.refElement, + isCalloutVisible: true, + YValueHover: found!.chartData, + hoverXValue: xAxisPoint, + stackCalloutProps: found!, }); }; @@ -391,10 +370,18 @@ export class VerticalStackedBarChartBase extends React.Component< let startingPointOfY = 0; const isCalloutForStack = this.props.isCalloutForStack || false; - const singleBar = singleChartData.chartData.map((point: IVSChartDataPoint, index: number) => { + let xPoint: number | string; + if (this._isNumeric) { + xPoint = xBarScale(singleChartData.xAxisPoint as number); + } else { + xPoint = xBarScale(indexNumber); + } + // Removing datapoints with zero data + const nonZeroBars = singleChartData.chartData.filter(point => point.data > 0); + const singleBar = nonZeroBars.map((point: IVSChartDataPoint, index: number) => { startingPointOfY = startingPointOfY + point.data; const color = point.color ? point.color : this._colors[index]; - const refArrayIndexNumber = indexNumber * singleChartData.chartData.length + index; + const ref: IRefArrayData = {}; let shouldHighlight = true; if (this.state.isLegendHovered || this.state.isLegendSelected) { @@ -405,20 +392,13 @@ export class VerticalStackedBarChartBase extends React.Component< shouldHighlight: shouldHighlight, href: this.props.href, }); - let xPoint; - if (this._isNumeric) { - xPoint = xBarScale(singleChartData.xAxisPoint as number); - } else { - xPoint = xBarScale(indexNumber); - } - const rectFocusProps = !isCalloutForStack && { 'data-is-focusable': true, 'aria-labelledby': this._calloutId, onMouseOver: this._onRectHover.bind(this, singleChartData.xAxisPoint, point), onMouseMove: this._onRectHover.bind(this, singleChartData.xAxisPoint, point), onMouseLeave: this._handleMouseOut, - onFocus: this._onRectFocus.bind(this, point, singleChartData.xAxisPoint, color, refArrayIndexNumber), + onFocus: this._onRectFocus.bind(this, point, singleChartData.xAxisPoint, color, ref), onBlur: this._handleMouseOut, onClick: this._redirectToUrl, }; @@ -431,19 +411,18 @@ export class VerticalStackedBarChartBase extends React.Component< width={this._barWidth} height={Math.max(yBarScale(point.data), 0)} fill={color} - ref={(e: SVGRectElement) => { - this._refCallback(e, point.legend, refArrayIndexNumber); - }} + ref={e => (ref.refElement = e)} {...rectFocusProps} /> ); }); + const groupRef: IRefArrayData = {}; const stackFocusProps = isCalloutForStack && { 'data-is-focusable': true, onMouseOver: this._onStackHover.bind(this, singleChartData.xAxisPoint), onMouseMove: this._onStackHover.bind(this, singleChartData.xAxisPoint), onMouseLeave: this._handleMouseOut, - onFocus: this._onStackFocus.bind(this, singleChartData.xAxisPoint), + onFocus: this._onStackFocus.bind(this, singleChartData.xAxisPoint, groupRef), onBlur: this._handleMouseOut, onClick: this._redirectToUrl, }; @@ -452,9 +431,7 @@ export class VerticalStackedBarChartBase extends React.Component< key={indexNumber} id={`${indexNumber}-singleBar`} data-is-focusable={this.props.isCalloutForStack} - ref={(gElement: SVGGElement) => { - this._barRefCallback(gElement, indexNumber, singleChartData.xAxisPoint); - }} + ref={e => (groupRef.refElement = e)} {...stackFocusProps} > {singleBar} @@ -482,7 +459,6 @@ export class VerticalStackedBarChartBase extends React.Component< private _createStringBars = (containerHeight: number, containerWidth: number): JSX.Element[] => { const yMax = this._getYMax(this._dataset); const endpointDistance = 0.5 * ((containerWidth - this.margins.right!) / this._dataset.length); - const xBarScale = d3ScaleLinear() .domain(this._isRtl ? [this._dataset.length - 1, 0] : [0, this._dataset.length - 1]) .range([ diff --git a/packages/react-examples/src/charting/VerticalStackedBarChart/VerticalStackedBarChart.Styled.Example.tsx b/packages/react-examples/src/charting/VerticalStackedBarChart/VerticalStackedBarChart.Styled.Example.tsx index d78e11f9d8410f..9ae6917584fd8b 100644 --- a/packages/react-examples/src/charting/VerticalStackedBarChart/VerticalStackedBarChart.Styled.Example.tsx +++ b/packages/react-examples/src/charting/VerticalStackedBarChart/VerticalStackedBarChart.Styled.Example.tsx @@ -37,7 +37,7 @@ export class VerticalStackedBarChartStyledExample extends React.Component<{}, IV const firstChartPoints: IVSChartDataPoint[] = [ { legend: 'Metadata1', data: 40, color: DefaultPalette.accent }, { legend: 'Metadata2', data: 5, color: DefaultPalette.blueMid }, - { legend: 'Metadata3', data: 15, color: DefaultPalette.blueLight }, + { legend: 'Metadata3', data: 0, color: DefaultPalette.blueLight }, ]; const secondChartPoints: IVSChartDataPoint[] = [ @@ -116,9 +116,10 @@ export class VerticalStackedBarChartStyledExample extends React.Component<{}, IV // eslint-disable-next-line react/jsx-no-bind yAxisTickFormat={(x: number | string) => `${x} h`} margins={{ - bottom: 40, - left: 45, - right: 30, + bottom: 0, + top: 0, + left: 0, + right: 0, }} legendProps={{ allowFocusOnLegends: true, @@ -128,7 +129,7 @@ export class VerticalStackedBarChartStyledExample extends React.Component<{}, IV }, }, }} - // eslint-disable-next-line react/jsx-no-bind @typescript-eslint/no-explicit-any + // eslint-disable-next-line react/jsx-no-bind, @typescript-eslint/no-explicit-any onRenderCalloutPerDataPoint={(props: any) => props ? (