Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react-charting): add functionality to export chart as image #33445

Merged
merged 16 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "feat: add functionality to export chart as image",
"packageName": "@fluentui/react-charting",
"email": "110246001+krkshitij@users.noreply.github.com",
"dependentChangeType": "patch"
}
34 changes: 34 additions & 0 deletions packages/charts/react-charting/etc/react-charting.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { IFocusZoneProps } from '@fluentui/react-focus';
import { IHoverCardStyleProps } from '@fluentui/react/lib/HoverCard';
import { IHoverCardStyles } from '@fluentui/react/lib/HoverCard';
import { IOverflowSetProps } from '@fluentui/react/lib/OverflowSet';
import { IRefObject } from '@fluentui/react/lib/Utilities';
import { IRenderFunction } from '@fluentui/react/lib/Utilities';
import { IStyle } from '@fluentui/react/lib/Styling';
import { IStyle as IStyle_2 } from '@fluentui/react';
Expand Down Expand Up @@ -125,6 +126,7 @@ export const DeclarativeChart: React_2.FunctionComponent<DeclarativeChartProps>;
// @public
export interface DeclarativeChartProps extends React_2.RefAttributes<HTMLDivElement> {
chartSchema: Schema;
componentRef?: IRefObject<IDeclarativeChart>;
onSchemaChange?: (eventData: Schema) => void;
}

Expand Down Expand Up @@ -267,6 +269,8 @@ export interface ICartesianChartProps {
// @deprecated
chartLabel?: string;
className?: string;
// (undocumented)
componentRef?: IRefObject<IChart>;
customDateTimeFormatter?: (dateTime: Date) => string;
dateLocalizeOptions?: Intl.DateTimeFormatOptions;
enabledLegendsWrapLines?: boolean;
Expand Down Expand Up @@ -352,6 +356,12 @@ export interface ICartesianChartStyles {
yAxis?: IStyle;
}

// @public (undocumented)
export interface IChart {
// (undocumented)
container: HTMLElement | null;
}

// @public (undocumented)
export interface IChartDataPoint {
callOutAccessibilityData?: IAccessibilityProps;
Expand Down Expand Up @@ -481,13 +491,21 @@ export interface IDataPoint {
y: number;
}

// @public (undocumented)
export interface IDeclarativeChart {
// (undocumented)
download: (opts?: IImageExportOptions) => Promise<string>;
}

// @public (undocumented)
export interface IDonutChart {
}

// @public
export interface IDonutChartProps extends ICartesianChartProps {
calloutProps?: Partial<ICalloutProps>;
// (undocumented)
componentRef?: IRefObject<IChart>;
culture?: string;
data?: IChartProps;
enableGradient?: boolean;
Expand Down Expand Up @@ -536,6 +554,8 @@ export interface IGaugeChartProps {
chartValue: number;
chartValueFormat?: GaugeValueFormat | ((sweepFraction: [number, number]) => string);
className?: string;
// (undocumented)
componentRef?: IRefObject<IChart>;
culture?: string;
enableGradient?: boolean;
height?: number;
Expand Down Expand Up @@ -832,6 +852,18 @@ export interface IHorizontalDataPoint {
y: number;
}

// @public (undocumented)
export interface IImageExportOptions {
// (undocumented)
background?: string;
// (undocumented)
height?: number;
// (undocumented)
scale?: number;
// (undocumented)
width?: number;
}

// @public
export interface ILegend {
action?: VoidFunction;
Expand Down Expand Up @@ -1200,6 +1232,8 @@ export interface ISankeyChartProps {
borderColorsForNodes?: string[];
className?: string;
colorsForNodes?: string[];
// (undocumented)
componentRef?: IRefObject<IChart>;
data: IChartProps;
enableReflow?: boolean;
formatNumberOptions?: Intl.NumberFormatOptions;
Expand Down
2 changes: 1 addition & 1 deletion packages/charts/react-charting/src/DeclarativeChart.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './components/DeclarativeChart/DeclarativeChart';
export * from './components/DeclarativeChart/index';
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { max as d3Max, bisector } from 'd3-array';
import { pointer } from 'd3-selection';
import { select as d3Select } from 'd3-selection';
import { area as d3Area, stack as d3Stack, curveMonotoneX as d3CurveBasis, line as d3Line } from 'd3-shape';
import { classNamesFunction, find, getId, memoizeFunction } from '@fluentui/react/lib/Utilities';
import {
classNamesFunction,
find,
getId,
initializeComponentRef,
memoizeFunction,
} from '@fluentui/react/lib/Utilities';
import {
IAccessibilityProps,
CartesianChart,
Expand Down Expand Up @@ -38,6 +44,7 @@ import {
} from '../../utilities/index';
import { ILegend, Legends } from '../Legends/index';
import { DirectionalHint } from '@fluentui/react/lib/Callout';
import { IChart } from '../../types/index';

const getClassNames = classNamesFunction<IAreaChartStyleProps, IAreaChartStyles>();

Expand Down Expand Up @@ -82,7 +89,7 @@ export interface IAreaChartState extends IBasestate {
activePoint: string;
}

export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartState> {
export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartState> implements IChart {
public static defaultProps: Partial<IAreaChartProps> = {
useUTC: true,
};
Expand Down Expand Up @@ -119,9 +126,13 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
private _enableComputationOptimization: boolean;
private _firstRenderOptimization: boolean;
private _emptyChartId: string;
private _cartesianChartRef: React.RefObject<IChart>;

public constructor(props: IAreaChartProps) {
super(props);

initializeComponentRef(this);
krkshitij marked this conversation as resolved.
Show resolved Hide resolved

this._createSet = memoizeFunction(this._createDataSet);
this.state = {
selectedLegend: props.legendProps?.selectedLegend ?? '',
Expand All @@ -148,6 +159,7 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
this._enableComputationOptimization = true;
this._firstRenderOptimization = true;
this._emptyChartId = getId('_AreaChart_empty');
this._cartesianChartRef = React.createRef();
}

public componentDidUpdate() {
Expand Down Expand Up @@ -212,6 +224,7 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
customizedCallout={this._getCustomizedCallout()}
onChartMouseLeave={this._handleChartMouseLeave}
enableFirstRenderOptimization={this.props.enablePerfOptimization && this._firstRenderOptimization}
componentRef={this._cartesianChartRef}
/* eslint-disable react/jsx-no-bind */
// eslint-disable-next-line react/no-children-prop
children={(props: IChildProps) => {
Expand Down Expand Up @@ -249,6 +262,10 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
);
}

public get container(): HTMLElement | null {
return this._cartesianChartRef.current?.container || null;
}

private _getDomainNRangeValues = (
points: ILineChartPoints[],
margins: IMargins,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { IProcessedStyleSet } from '@fluentui/react/lib/Styling';
import { classNamesFunction, getId, getRTL } from '@fluentui/react/lib/Utilities';
import { classNamesFunction, getId, getRTL, initializeComponentRef } from '@fluentui/react/lib/Utilities';
import { Callout } from '@fluentui/react/lib/Callout';
import { FocusZone, FocusZoneDirection } from '@fluentui/react-focus';
import {
Expand Down Expand Up @@ -32,6 +32,7 @@ import {
} from '../../utilities/index';
import { LegendShape, Shape } from '../Legends/index';
import { SVGTooltipText } from '../../utilities/SVGTooltipText';
import { IChart } from '../../types/index';

const getClassNames = classNamesFunction<ICartesianChartStyleProps, ICartesianChartStyles>();
const ChartHoverCard = React.lazy(() =>
Expand Down Expand Up @@ -63,7 +64,10 @@ export interface ICartesianChartState {
* 2.Callout
* 3.Fit parent Continer
*/
export class CartesianChartBase extends React.Component<IModifiedCartesianChartProps, ICartesianChartState> {
export class CartesianChartBase
extends React.Component<IModifiedCartesianChartProps, ICartesianChartState>
implements IChart
{
private _classNames: IProcessedStyleSet<ICartesianChartStyles>;
private chartContainer: HTMLDivElement;
private legendContainer: HTMLDivElement;
Expand All @@ -86,6 +90,9 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP

constructor(props: IModifiedCartesianChartProps) {
super(props);

initializeComponentRef(this);

this.state = {
containerHeight: 0,
containerWidth: 0,
Expand Down Expand Up @@ -619,6 +626,11 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
</div>
);
}

public get container(): HTMLElement | null {
return this.chartContainer;
}

/**
* Dedicated function to return the Callout JSX Element , which can further be used to only call this when
* only the calloutprops and charthover props changes.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import * as React from 'react';
import { IStyleFunctionOrObject } from '@fluentui/react/lib/Utilities';
import { IRefObject, IStyleFunctionOrObject } from '@fluentui/react/lib/Utilities';
import { ITheme, IStyle } from '@fluentui/react/lib/Styling';
import { IOverflowSetProps } from '@fluentui/react/lib/OverflowSet';
import { IFocusZoneProps, FocusZoneDirection } from '@fluentui/react-focus';
import { ICalloutProps } from '@fluentui/react/lib/Callout';
import { ILegendsProps } from '../Legends/index';
import {
IAccessibilityProps,
IChart,
IDataPoint,
IGroupedVerticalBarChartData,
IHeatMapChartDataPoint,
Expand Down Expand Up @@ -445,6 +446,8 @@ export interface ICartesianChartProps {
* Used for enabling negative values in Y axis.
*/
supportNegativeData?: boolean;

componentRef?: IRefObject<IChart>;
}

export interface IYValueHover {
Expand Down
Loading
Loading