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): use legend data and config from Legends component for image export #33847

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
Prev Previous commit
Next Next commit
refactor
  • Loading branch information
krkshitij committed Feb 18, 2025
commit d93b9bdbccac6674a1b414ecc846fc9b7b6a6689
14 changes: 12 additions & 2 deletions packages/charts/react-charting/etc/react-charting.api.md
Original file line number Diff line number Diff line change
@@ -361,8 +361,6 @@ export interface ICartesianChartStyles {
export interface IChart {
// (undocumented)
chartContainer: HTMLElement | null;
// Warning: (ae-forgotten-export) The symbol "IImageExportOptions" needs to be exported by the entry point index.d.ts
//
// (undocumented)
toImage?: (opts?: IImageExportOptions) => Promise<string>;
}
@@ -858,6 +856,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;
Original file line number Diff line number Diff line change
@@ -279,8 +279,7 @@ export class AreaChartBase extends React.Component<IAreaChartProps, IAreaChartSt
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = getRTL() ? 'rtl' : 'ltr';
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, getRTL(), opts);
};

private _getDomainNRangeValues = (
Original file line number Diff line number Diff line change
@@ -217,8 +217,7 @@ export class DonutChartBase extends React.Component<IDonutChartProps, IDonutChar
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = getRTL() ? 'rtl' : 'ltr';
return toImage(this._rootElem, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._rootElem, this._legendsRef.current?.toSVG, getRTL(), opts);
};

private _closeCallout = () => {
Original file line number Diff line number Diff line change
@@ -364,8 +364,7 @@ export class GaugeChartBase extends React.Component<IGaugeChartProps, IGaugeChar
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = this._isRTL ? 'rtl' : 'ltr';
return toImage(this._rootElem, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._rootElem, this._legendsRef.current?.toSVG, this._isRTL, opts);
};

private _getMargins = () => {
Original file line number Diff line number Diff line change
@@ -252,8 +252,7 @@ export class GroupedVerticalBarChartBase
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = this._isRtl ? 'rtl' : 'ltr';
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, this._isRtl, opts);
};

private _getMinMaxOfYAxis = () => {
Original file line number Diff line number Diff line change
@@ -270,8 +270,7 @@ export class HeatMapChartBase extends React.Component<IHeatMapChartProps, IHeatM
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = getRTL() ? 'rtl' : 'ltr';
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, getRTL(), opts);
};

private _getMinMaxOfYAxis = () => {
Original file line number Diff line number Diff line change
@@ -204,8 +204,7 @@ export class HorizontalBarChartWithAxisBase
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = this._isRtl ? 'rtl' : 'ltr';
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, this._isRtl, opts);
};

private _getDomainNRangeValues = (
Original file line number Diff line number Diff line change
@@ -121,12 +121,12 @@ export class LegendsBase extends React.Component<ILegendsProps, ILegendState> im
);
}

public toSVG = (svgWidth: number, direction: 'ltr' | 'rtl' = 'ltr') => {
public toSVG = (svgWidth: number, isRTL: boolean = false) => {
return cloneLegendsToSVG(this.props.legends, svgWidth, {
selectedLegends: this.state.selectedLegends,
centerLegends: !!this.props.centerLegends,
textClassName: this._classNames.text,
isRTL: direction === 'rtl',
isRTL,
});
};

Original file line number Diff line number Diff line change
@@ -295,10 +295,13 @@ export interface ILegendsProps {
*/
export type LegendShape = 'default' | 'triangle' | keyof typeof Points | keyof typeof CustomPoints;

/**
* {@docCategory Legends}
*/
export interface ILegendContainer {
toSVG: (
svgWidth: number,
direction?: 'ltr' | 'rtl',
isRTL?: boolean,
) => {
node: SVGGElement | null;
width: number;
Original file line number Diff line number Diff line change
@@ -383,8 +383,7 @@ export class LineChartBase extends React.Component<ILineChartProps, ILineChartSt
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = this._isRTL ? 'rtl' : 'ltr';
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, this._isRTL, opts);
};

private _getDomainNRangeValues = (
Original file line number Diff line number Diff line change
@@ -899,8 +899,7 @@ export class SankeyChartBase extends React.Component<ISankeyChartProps, ISankeyC
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = this._isRtl ? 'rtl' : 'ltr';
return toImage(this.chartContainer, undefined, direction, opts);
return toImage(this.chartContainer, undefined, this._isRtl, opts);
};

private _computeNodeAttributes(
Original file line number Diff line number Diff line change
@@ -261,8 +261,7 @@ export class VerticalBarChartBase
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = this._isRtl ? 'rtl' : 'ltr';
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, this._isRtl, opts);
};

private _getDomainNRangeValues = (
Original file line number Diff line number Diff line change
@@ -300,8 +300,7 @@ export class VerticalStackedBarChartBase
}

public toImage = (opts?: IImageExportOptions): Promise<string> => {
const direction = this._isRtl ? 'rtl' : 'ltr';
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, direction, opts);
return toImage(this._cartesianChartRef.current?.chartContainer, this._legendsRef.current?.toSVG, this._isRtl, opts);
};

/**
1 change: 1 addition & 0 deletions packages/charts/react-charting/src/index.ts
Original file line number Diff line number Diff line change
@@ -98,6 +98,7 @@ export type {
SLink,
SNode,
IChart,
IImageExportOptions,
} from './types/index';
export type {
IChartHoverCardProps,
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import { ILegend, ILegendContainer } from '../Legends';
export function toImage(
chartContainer: HTMLElement | null | undefined,
legendsToSvgCallback?: ILegendContainer['toSVG'],
direction: 'ltr' | 'rtl' = 'ltr',
isRTL: boolean = false,
opts: IImageExportOptions = {},
): Promise<string> {
return new Promise((resolve, reject) => {
@@ -17,7 +17,7 @@ export function toImage(
try {
const background =
typeof opts.background === 'string' ? resolveCSSVariables(chartContainer, opts.background) : 'transparent';
const svg = toSVG(chartContainer, legendsToSvgCallback, direction, background);
const svg = toSVG(chartContainer, legendsToSvgCallback, isRTL, background);

const svgData = new XMLSerializer().serializeToString(svg.node);
const svgDataUrl = 'data:image/svg+xml;base64,' + btoa(unescapePonyfill(encodeURIComponent(svgData)));
@@ -41,7 +41,7 @@ const SVG_TEXT_STYLE_PROPERTIES = ['font-family', 'font-size', 'font-weight', 't
function toSVG(
chartContainer: HTMLElement,
legendsToSvgCallback: ILegendContainer['toSVG'] | undefined,
direction: 'ltr' | 'rtl',
isRTL: boolean,
background: string,
) {
const svg = chartContainer.querySelector<SVGSVGElement>('svg');
@@ -67,7 +67,7 @@ function toSVG(
const { width: svgWidth, height: svgHeight } = svg.getBoundingClientRect();
const legendGroup =
typeof legendsToSvgCallback === 'function'
? legendsToSvgCallback(svgWidth, direction)
? legendsToSvgCallback(svgWidth, isRTL)
: { node: null, width: 0, height: 0 };
const w1 = Math.max(svgWidth, legendGroup.width);
const h1 = svgHeight + legendGroup.height;
@@ -83,7 +83,11 @@ function toSVG(
.attr('width', w1)
.attr('height', h1)
.attr('fill', background);
clonedSvg.attr('width', w1).attr('height', h1).attr('viewBox', `0 0 ${w1} ${h1}`).attr('direction', direction);
clonedSvg
.attr('width', w1)
.attr('height', h1)
.attr('viewBox', `0 0 ${w1} ${h1}`)
.attr('direction', isRTL ? 'rtl' : 'ltr');

return {
node: clonedSvg.node()!,
Loading
Oops, something went wrong.