Skip to content

Commit 0ce8d43

Browse files
authored
feat(charts): add support for lines in GVBC (microsoft#35135)
1 parent 7afaa51 commit 0ce8d43

21 files changed

+1304
-389
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "feat: add support for lines in GVBC",
4+
"packageName": "@fluentui/chart-utilities",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "feat: add support for lines in GVBC",
4+
"packageName": "@fluentui/react-charting",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/charts/chart-utilities/etc/chart-utilities.api.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,9 @@ export const isNumberArray: (data: Datum[] | Datum[][] | TypedArray | undefined)
520520
// @public (undocumented)
521521
export const isObjectArray: (data: Datum[] | Datum[][] | TypedArray | undefined) => boolean;
522522

523+
// @public (undocumented)
524+
export const isScatterAreaChart: (data: Partial<PlotData>) => boolean;
525+
523526
// @public (undocumented)
524527
export const isStringArray: (data: Datum[] | Datum[][] | TypedArray | undefined) => boolean;
525528

packages/charts/chart-utilities/src/PlotlySchemaConverter.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ const validateScatterData = (data: Partial<PlotData>, layout: Partial<Layout> |
302302
}
303303

304304
const isAreaChart = isScatterAreaChart(data);
305-
const isFallbackNeeded = doesScatterNeedVSBCFallback(data);
305+
const isFallbackNeeded = doesScatterNeedFallback(data);
306306
if (isAreaChart && isFallbackNeeded) {
307307
throw new Error(
308308
`${UNSUPPORTED_MSG_PREFIX} ${data.type}, Fallback to VerticalStackedBarChart is not allowed for Area Charts.`,
@@ -542,11 +542,11 @@ export const mapFluentChart = (input: any): OutputChartType => {
542542
return { isValid: true, traceIndex, type: 'scatter' };
543543
}
544544

545-
if (!doesScatterNeedVSBCFallback(scatterData)) {
545+
if (!doesScatterNeedFallback(scatterData)) {
546546
return { isValid: true, traceIndex, type: isAreaChart ? 'area' : 'line' };
547547
}
548548

549-
// isScatterAreaChart and doesScatterNeedVSBCFallback cannot both return true for the
549+
// isScatterAreaChart and doesScatterNeedFallback cannot both return true for the
550550
// same trace due to the validation logic in validateScatterData.
551551
return { isValid: true, traceIndex, type: 'fallback' };
552552
default:
@@ -581,12 +581,23 @@ export const mapFluentChart = (input: any): OutputChartType => {
581581
trace => trace.type === 'groupedverticalbar' || trace.type === 'verticalstackedbar',
582582
);
583583
const containsLines = mappedTraces.some(trace => trace.type === 'line' || trace.type === 'fallback');
584-
if (containsBars && containsLines) {
585-
return {
586-
isValid: true,
587-
type: 'fallback',
588-
validTracesInfo: tracesInfo,
589-
};
584+
if (containsLines) {
585+
if (containsBars) {
586+
const shouldUseGVBC = !mappedTraces.some(trace => trace.type === 'verticalstackedbar');
587+
return {
588+
isValid: true,
589+
type: shouldUseGVBC ? 'groupedverticalbar' : 'fallback',
590+
validTracesInfo: tracesInfo,
591+
};
592+
}
593+
594+
if (mappedTraces.some(trace => trace.type === 'fallback')) {
595+
return {
596+
isValid: true,
597+
type: 'fallback',
598+
validTracesInfo: tracesInfo,
599+
};
600+
}
590601
}
591602

592603
const uniqueTypes = new Set(mappedTraces.map(trace => trace.type));
@@ -634,11 +645,11 @@ export const getAxisKey = (axLetter: 'x' | 'y', axId: number) => {
634645
return `${axLetter}axis${axId > 1 ? axId : ''}` as keyof Layout;
635646
};
636647

637-
const isScatterAreaChart = (data: Partial<PlotData>) => {
648+
export const isScatterAreaChart = (data: Partial<PlotData>) => {
638649
return data.fill === 'tonexty' || data.fill === 'tozeroy' || !!data.stackgroup;
639650
};
640651

641-
const doesScatterNeedVSBCFallback = (data: Partial<PlotData>) => {
652+
const doesScatterNeedFallback = (data: Partial<PlotData>) => {
642653
if (isScatterMarkers(data.mode ?? '')) {
643654
return false;
644655
}

packages/charts/chart-utilities/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ export {
117117
isObjectArray,
118118
getAxisIds,
119119
getAxisKey,
120+
isScatterAreaChart,
120121
} from './PlotlySchemaConverter';
121122

122123
export { decodeBase64Fields } from './DecodeBase64Data';

packages/charts/react-charting/etc/react-charting.api.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,13 @@ export interface IAreaChartStyleProps extends ICartesianChartStyleProps {
242242
export interface IAreaChartStyles extends ICartesianChartStyles {
243243
}
244244

245+
// @public
246+
export interface IBarSeries<X extends string | number | Date, Y extends string | number | Date> extends IDataSeries {
247+
data: IDataPointV2<X, Y>[];
248+
key?: string;
249+
type: 'bar';
250+
}
251+
245252
// @public (undocumented)
246253
export interface IBaseDataPoint {
247254
callOutAccessibilityData?: IAccessibilityProps;
@@ -589,6 +596,30 @@ export interface IDataPoint {
589596
y: number;
590597
}
591598

599+
// @public
600+
export interface IDataPointV2<X extends string | number | Date, Y extends string | number | Date> {
601+
callOutAccessibilityData?: IAccessibilityProps;
602+
color?: string;
603+
markerSize?: number;
604+
onClick?: () => void;
605+
text?: string;
606+
x: X;
607+
xAxisCalloutData?: string;
608+
y: Y;
609+
yAxisCalloutData?: string;
610+
}
611+
612+
// @public
613+
export interface IDataSeries {
614+
color?: string;
615+
gradient?: [string, string];
616+
legend: string;
617+
legendShape?: LegendShape;
618+
onLegendClick?: (selectedLegend: string | null | string[]) => void;
619+
opacity?: number;
620+
useSecondaryYScale?: boolean;
621+
}
622+
592623
// @public (undocumented)
593624
export interface IDeclarativeChart {
594625
// (undocumented)
@@ -809,7 +840,8 @@ export interface IGroupedVerticalBarChartProps extends ICartesianChartProps {
809840
barwidth?: number | 'default' | 'auto';
810841
chartTitle?: string;
811842
culture?: string;
812-
data: IGroupedVerticalBarChartData[];
843+
data?: IGroupedVerticalBarChartData[];
844+
dataV2?: (IBarSeries<string, number> | ILineSeries<string, number>)[];
813845
enableGradient?: boolean;
814846
hideLabels?: boolean;
815847
isCalloutForStack?: boolean;
@@ -845,7 +877,7 @@ export interface IGroupedVerticalBarChartStyles extends ICartesianChartStyles {
845877
// @public (undocumented)
846878
export interface IGVBarChartSeriesPoint {
847879
callOutAccessibilityData?: IAccessibilityProps;
848-
color: string;
880+
color?: string;
849881
data: number;
850882
gradient?: [string, string];
851883
key: string;
@@ -1233,6 +1265,16 @@ export interface ILineDataInVerticalStackedBarChart {
12331265
yAxisCalloutData?: string;
12341266
}
12351267

1268+
// @public
1269+
export interface ILineSeries<X extends string | number | Date, Y extends string | number | Date> extends IDataSeries {
1270+
data: IDataPointV2<X, Y>[];
1271+
gaps?: ILineChartGap[];
1272+
hideInactiveDots?: boolean;
1273+
lineOptions?: ILineChartLineOptions;
1274+
onLineClick?: () => void;
1275+
type: 'line';
1276+
}
1277+
12361278
// @public (undocumented)
12371279
export interface IMargins {
12381280
bottom?: number;

packages/charts/react-charting/src/components/DeclarativeChart/DeclarativeChart.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ const ResponsiveGanttChart = withResponsiveContainer(GanttChart);
6767

6868
// Default x-axis key for grouping traces. Also applicable for PieData and SankeyData where x-axis is not defined.
6969
const DEFAULT_XAXIS = 'x';
70-
const FALLBACK_TYPE = 'fallback';
7170

7271
/**
7372
* DeclarativeChart schema.
@@ -499,9 +498,7 @@ export const DeclarativeChart: React.FunctionComponent<DeclarativeChartProps> =
499498

500499
const filteredTracesInfo = validTracesFilteredIndex.filter(trace => index.includes(trace.index));
501500
let chartType =
502-
validTracesFilteredIndex.some(trace => trace.type === FALLBACK_TYPE) || chart.type === FALLBACK_TYPE
503-
? FALLBACK_TYPE
504-
: filteredTracesInfo[0].type;
501+
chart.type === 'fallback' || chart.type === 'groupedverticalbar' ? chart.type : filteredTracesInfo[0].type;
505502

506503
if (
507504
validTracesFilteredIndex.some(trace => trace.type === 'line') &&

0 commit comments

Comments
 (0)