Skip to content

Commit b464615

Browse files
Anush2303Anush
andauthored
feat(declarative-charts): Add Support for Plotly generated tables (#34461)
Co-authored-by: Anush <anushgupta@microsoft.com>
1 parent 476da26 commit b464615

19 files changed

Lines changed: 1097 additions & 3 deletions
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Add support for plotly generated tables",
4+
"packageName": "@fluentui/chart-utilities",
5+
"email": "anushgupta@microsoft.com",
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": "Add support for plotly generated tables",
4+
"packageName": "@fluentui/react-charting",
5+
"email": "anushgupta@microsoft.com",
6+
"dependentChangeType": "patch"
7+
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,6 +1855,38 @@ export interface ShapeLine {
18551855
width: number;
18561856
}
18571857

1858+
// @public (undocumented)
1859+
export interface TableData {
1860+
// (undocumented)
1861+
cells?: {
1862+
align?: 'left' | 'center' | 'right' | ('left' | 'center' | 'right')[];
1863+
fill?: {
1864+
color?: Color | Color[];
1865+
};
1866+
font?: {
1867+
family?: string | string[];
1868+
size?: number | number[];
1869+
color?: Color | Color[];
1870+
};
1871+
values: (string | number | boolean | null)[][];
1872+
};
1873+
// (undocumented)
1874+
header?: {
1875+
align?: 'left' | 'center' | 'right' | ('left' | 'center' | 'right')[];
1876+
fill?: {
1877+
color?: Color | Color[];
1878+
};
1879+
font?: {
1880+
family?: string | string[];
1881+
size?: number | number[];
1882+
color?: Color | Color[];
1883+
};
1884+
values: (string | number | boolean | null)[];
1885+
};
1886+
// (undocumented)
1887+
type: 'table';
1888+
}
1889+
18581890
// @public (undocumented)
18591891
export interface Template {
18601892
// (undocumented)

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,34 @@ export interface PlotData {
13271327
base: Datum[] | Datum[][] | TypedArray;
13281328
}
13291329

1330+
export interface TableData {
1331+
type: 'table';
1332+
header?: {
1333+
align?: 'left' | 'center' | 'right' | ('left' | 'center' | 'right')[];
1334+
fill?: {
1335+
color?: Color | Color[];
1336+
};
1337+
font?: {
1338+
family?: string | string[];
1339+
size?: number | number[];
1340+
color?: Color | Color[];
1341+
};
1342+
values: (string | number | boolean | null)[];
1343+
};
1344+
cells?: {
1345+
align?: 'left' | 'center' | 'right' | ('left' | 'center' | 'right')[];
1346+
fill?: {
1347+
color?: Color | Color[];
1348+
};
1349+
font?: {
1350+
family?: string | string[];
1351+
size?: number | number[];
1352+
color?: Color | Color[];
1353+
};
1354+
values: (string | number | boolean | null)[][];
1355+
};
1356+
}
1357+
13301358
/**
13311359
* These interfaces are based on attribute descriptions in
13321360
* https://github.com/plotly/plotly.js/tree/9d6144304308fc3007f0facf2535d38ea3e9b26c/src/transforms

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ export const mapFluentChart = (input: any): OutputChartType => {
251251
return { isValid: true, type: 'verticalbar', validTracesInfo: validTraces };
252252
case 'scatterpolar':
253253
return { isValid: true, type: 'scatterpolar', validTracesInfo: validTraces };
254+
case 'table':
255+
return { isValid: true, type: 'table', validTracesInfo: validTraces };
254256
default:
255257
const containsBars = validTraces.some(trace => validSchema.data[trace[0]].type === 'bar');
256258
const containsLines = validTraces.some(trace => validSchema.data[trace[0]].type === 'scatter');

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export type {
9292
TypedArray,
9393
XAxisName,
9494
YAxisName,
95+
TableData,
9596
} from './PlotlySchema';
9697

9798
export type { OutputChartType } from './PlotlySchemaConverter';

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ export type ChartDataMode = 'default' | 'fraction' | 'percentage';
4040
// @public (undocumented)
4141
export const ChartHoverCard: React_2.FunctionComponent<IChartHoverCardProps>;
4242

43+
// @public
44+
export const ChartTable: React_2.FunctionComponent<IChartTableProps>;
45+
4346
// @public (undocumented)
4447
export const DataVizGradientPalette: {
4548
gradient1: string;
@@ -432,6 +435,38 @@ export interface IChartProps {
432435
SankeyChartData?: ISankeyChartData;
433436
}
434437

438+
// @public
439+
export interface IChartTableProps {
440+
className?: string;
441+
componentRef?: IRefObject<IChart>;
442+
headers: (string | number | boolean | null)[] | (string | number | boolean | null)[][];
443+
height?: string | number;
444+
rows: (string | number | boolean | null)[][];
445+
styles?: IStyleFunctionOrObject<IChartTableStyleProps, IChartTableStyles>;
446+
theme?: ITheme;
447+
width?: string | number;
448+
}
449+
450+
// @public (undocumented)
451+
export interface IChartTableStyleProps {
452+
// (undocumented)
453+
className?: string;
454+
// (undocumented)
455+
theme: ITheme;
456+
}
457+
458+
// @public
459+
export interface IChartTableStyles {
460+
// (undocumented)
461+
bodyCell?: IStyle;
462+
// (undocumented)
463+
headerCell?: IStyle;
464+
// (undocumented)
465+
root?: IStyle;
466+
// (undocumented)
467+
table?: IStyle;
468+
}
469+
435470
// @public (undocumented)
436471
export interface IChildProps {
437472
// (undocumented)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './components/ChartTable/index';
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import * as React from 'react';
2+
import { IChartTableProps } from './ChartTable.types';
3+
import { IChartTableStyleProps, IChartTableStyles } from '../../index';
4+
import { classNamesFunction, getRTL, initializeComponentRef } from '@fluentui/react/lib/Utilities';
5+
import { IImageExportOptions } from '../../types/index';
6+
import { toImage } from '../../utilities/image-export-utils';
7+
8+
const getClassNames = classNamesFunction<IChartTableStyleProps, IChartTableStyles>();
9+
10+
export class ChartTableBase extends React.Component<IChartTableProps> {
11+
private _isRTL: boolean;
12+
private _rootElem: HTMLDivElement | null;
13+
14+
constructor(props: IChartTableProps) {
15+
super(props);
16+
initializeComponentRef(this);
17+
this._isRTL = getRTL(props.theme);
18+
}
19+
public toImage = (opts?: IImageExportOptions): Promise<string> => {
20+
return toImage(this._rootElem, undefined, this._isRTL, opts);
21+
};
22+
23+
public render(): JSX.Element {
24+
const { headers, rows, width, height, styles, theme } = this.props;
25+
26+
const classNames = getClassNames(styles!, {
27+
theme: theme!,
28+
});
29+
30+
if (!headers || headers.length === 0) {
31+
return <div>No data available</div>;
32+
}
33+
34+
return (
35+
<div
36+
ref={el => (this._rootElem = el)}
37+
className={classNames.root}
38+
style={{ height: height ? `${height}px` : '650px', overflow: 'hidden' }}
39+
>
40+
<svg width={width ?? '100%'} height={height ?? '650px'}>
41+
<foreignObject x="0" y="0" width="100%" height="100%">
42+
<div
43+
style={{
44+
maxHeight: height ? `${height}px` : '650px',
45+
overflowY: 'auto',
46+
overflowX: 'auto',
47+
}}
48+
>
49+
<table
50+
className={classNames.table}
51+
style={{
52+
width: width ? `${width}px` : '100%',
53+
}}
54+
>
55+
<thead>
56+
<tr>
57+
{headers.map((header, idx) => (
58+
<th key={idx} className={classNames.headerCell}>
59+
{header}
60+
</th>
61+
))}
62+
</tr>
63+
</thead>
64+
{rows && rows.length > 0 && (
65+
<tbody>
66+
{rows.map((row, rowIdx) => (
67+
<tr key={rowIdx}>
68+
{row.map((cell, colIdx) => (
69+
<td key={colIdx} className={classNames.bodyCell}>
70+
{cell}
71+
</td>
72+
))}
73+
</tr>
74+
))}
75+
</tbody>
76+
)}
77+
</table>
78+
</div>
79+
</foreignObject>
80+
</svg>
81+
</div>
82+
);
83+
}
84+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { IChartTableStyleProps, IChartTableStyles } from './ChartTable.types';
2+
import { FontWeights, HighContrastSelector } from '@fluentui/react/lib/Styling';
3+
4+
export const getStyles = (props: IChartTableStyleProps): IChartTableStyles => {
5+
const { theme } = props;
6+
const { fonts } = theme!;
7+
8+
return {
9+
root: {
10+
width: '100%',
11+
overflowX: 'auto',
12+
},
13+
table: {
14+
borderCollapse: 'collapse',
15+
},
16+
headerCell: {
17+
...fonts.small,
18+
fontWeight: FontWeights.semibold,
19+
backgroundColor: theme!.palette.neutralQuaternary,
20+
color: theme!.semanticColors.bodyText,
21+
padding: '8px',
22+
textAlign: 'left',
23+
border: `2px solid ${theme!.palette.neutralLighter}`,
24+
selectors: {
25+
[HighContrastSelector]: {
26+
backgroundColor: 'Window',
27+
color: 'WindowText',
28+
},
29+
},
30+
},
31+
bodyCell: {
32+
...fonts.small,
33+
padding: '8px',
34+
border: `2px solid ${theme!.palette.neutralLighter}`,
35+
color: theme!.semanticColors.bodyText,
36+
textAlign: 'left',
37+
selectors: {
38+
[HighContrastSelector]: {
39+
color: 'WindowText',
40+
},
41+
},
42+
},
43+
};
44+
};

0 commit comments

Comments
 (0)