@patternfly/react-charts
Version:
This library provides a set of React chart components for use with the PatternFly reference implementation.
371 lines • 13.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLegendItemsExtraHeight = exports.getLegendDimensions = exports.getComputedLegend = exports.getLegendMaxTextWidth = void 0;
const tslib_1 = require("tslib");
const react_1 = require("react");
const defaults_1 = tslib_1.__importDefault(require("lodash/defaults"));
const victory_core_1 = require("victory-core");
const victory_legend_1 = require("victory-legend");
const ChartStyles_1 = require("../ChartTheme/ChartStyles");
const chart_label_1 = require("../ChartUtils/chart-label");
const chart_origin_1 = require("./chart-origin");
/**
* Returns the max text length in a legend data set to calculate the x offset for right aligned legends.
*
* @private Not intended as public API and subject to change
*/
const getLegendMaxTextWidth = (legendData, theme) => {
let legendXOffset = 0;
legendData.map((data) => {
const labelWidth = (0, chart_label_1.getLabelTextSize)({ text: data.name, theme }).width;
if (labelWidth > legendXOffset) {
legendXOffset = labelWidth;
}
});
return legendXOffset;
};
exports.getLegendMaxTextWidth = getLegendMaxTextWidth;
/**
* Returns a legend which has been positioned per the given chart properties
*
* @private Not intended as public API and subject to change
*/
const getComputedLegend = ({ allowWrap = true, chartType = 'chart', colorScale, dx = 0, dy = 0, height, legendComponent, padding, patternScale, position = ChartStyles_1.ChartCommonStyles.legend.position, theme, themeColor, width,
// destructure last
orientation = theme.legend.orientation }) => {
// Get the number of legend items per row
const legendItemsProps = legendComponent.props ? legendComponent.props : {};
const legendItemsPerRow = allowWrap
? getLegendItemsPerRow({
dx,
height,
legendData: legendItemsProps.data,
legendOrientation: legendItemsProps.legendOrientation ? legendItemsProps.legendOrientation : orientation,
legendPosition: position,
legendProps: legendItemsProps,
padding,
theme,
width
})
: undefined;
// Include new itemsPerRow prop when determining x and y position
const legendPositionProps = (0, defaults_1.default)({}, legendComponent.props, {
itemsPerRow: legendItemsPerRow
});
const legendX = getLegendX({
chartType,
dx,
height,
legendData: legendPositionProps.data,
legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation,
legendPosition: position,
legendProps: legendPositionProps,
padding,
theme,
width
});
const legendY = getLegendY({
chartType,
dy,
height,
legendData: legendPositionProps.data,
legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation,
legendProps: legendPositionProps,
legendPosition: position,
padding,
theme,
width
});
// Clone legend with updated props
const legendProps = (0, defaults_1.default)({}, legendComponent.props, {
colorScale,
itemsPerRow: legendItemsPerRow,
orientation,
patternScale,
standalone: false,
theme,
themeColor,
x: legendX > 0 ? legendX : 0,
y: legendY > 0 ? legendY : 0
});
return (0, react_1.cloneElement)(legendComponent, legendProps);
};
exports.getComputedLegend = getComputedLegend;
/**
* Returns legend dimensions
*
* @private Not intended as public API and subject to change
*/
const getLegendDimensions = ({ legendData, legendOrientation, legendProps, theme }) => {
if (legendData || legendProps.data) {
return victory_legend_1.VictoryLegend.getDimensions(Object.assign({ data: legendData, orientation: legendOrientation, theme }, legendProps // override above
));
}
return {};
};
exports.getLegendDimensions = getLegendDimensions;
/**
* Returns true if the legend is smaller than its container
*
* @private Not intended as public API and subject to change
*/
const doesLegendFit = ({ dx = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => {
const { left, right } = victory_core_1.Helpers.getPadding(padding);
const chartSize = {
height, // Fixed size
width: width - left - right
};
const legendDimensions = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps,
theme
});
let occupiedWidth = 0;
switch (legendPosition) {
case 'bottom-left':
occupiedWidth = left + dx;
break;
case 'right':
occupiedWidth = chartSize.width + ChartStyles_1.ChartCommonStyles.legend.margin + left + dx;
break;
default:
occupiedWidth = dx;
break;
}
return width - occupiedWidth > legendDimensions.width;
};
/**
* Returns the number of legend items per row
*
* @private Not intended as public API and subject to change
*/
const getLegendItemsPerRow = ({ dx, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => {
let itemsPerRow = legendData ? legendData.length : 0;
for (let i = itemsPerRow; i > 0; i--) {
const fits = doesLegendFit({
dx,
height,
legendPosition,
legendData,
legendOrientation,
legendProps: Object.assign(Object.assign({}, legendProps), { itemsPerRow: i }),
padding,
theme,
width
});
if (fits) {
itemsPerRow = i;
break;
}
}
return itemsPerRow;
};
/**
* Returns the extra height required to accommodate wrapped legend items
*
* @private Not intended as public API and subject to change
*/
const getLegendItemsExtraHeight = ({ legendData, legendOrientation, legendProps, theme }) => {
// Get legend dimensions
const legendDimensions = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps,
theme
});
// Get legend dimensions without any wrapped items
const legendDimensionsNoWrap = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps: Object.assign(Object.assign({}, legendProps), { itemsPerRow: undefined }),
theme
});
return Math.abs(legendDimensions.height - legendDimensionsNoWrap.height);
};
exports.getLegendItemsExtraHeight = getLegendItemsExtraHeight;
/**
* Returns x coordinate for legend
*
* @private Not intended as public API and subject to change
*/
const getLegendX = (_a) => {
var { chartType } = _a, rest = tslib_1.__rest(_a, ["chartType"]);
return chartType === 'pie' ? getPieLegendX(rest) : getChartLegendX(rest);
};
/**
* Returns y coordinate for legend
*
* @private Not intended as public API and subject to change
*/
const getLegendY = (_a) => {
var { chartType } = _a, rest = tslib_1.__rest(_a, ["chartType"]);
switch (chartType) {
case 'pie':
return getPieLegendY(rest);
case 'bullet':
return getBulletLegendY(rest);
default:
return getChartLegendY(rest);
}
};
/**
* Returns y coordinate for bullet legends
*
* @private Not intended as public API and subject to change
*/
const getBulletLegendY = ({ dy = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => {
const { left, right } = victory_core_1.Helpers.getPadding(padding);
const chartSize = {
height, // Fixed size
width: width - left - right
};
switch (legendPosition) {
case 'bottom':
case 'bottom-left':
return chartSize.height + ChartStyles_1.ChartCommonStyles.legend.margin + dy;
case 'right': {
// Legend height with padding
const legendDimensions = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps,
theme
});
const legendPadding = (legendDataArr) => (legendDataArr && legendDataArr.length > 0 ? 17 : 0);
return (chartSize.height - legendDimensions.height) / 2 + legendPadding(legendData);
}
default:
return dy;
}
};
/**
* Returns x coordinate for chart legends
*
* @private Not intended as public API and subject to change
*/
const getChartLegendX = ({ dx = 0, height, legendData, legendOrientation, legendPosition, legendProps, padding, theme, width }) => {
const { top, bottom, left, right } = victory_core_1.Helpers.getPadding(padding);
const chartSize = {
height: Math.abs(height - (bottom + top)),
width: Math.abs(width - (left + right))
};
const legendDimensions = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps,
theme
});
switch (legendPosition) {
case 'bottom':
return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx;
case 'bottom-left':
return left + dx;
case 'right':
return chartSize.width + ChartStyles_1.ChartCommonStyles.legend.margin + left + dx;
default:
return dx;
}
};
/**
* Returns y coordinate for chart legends
*
* @private Not intended as public API and subject to change
*/
const getChartLegendY = ({ dy = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => {
const { top, bottom, left, right } = victory_core_1.Helpers.getPadding(padding);
const chartSize = {
height: Math.abs(height - (bottom + top)),
width: Math.abs(width - (left + right))
};
switch (legendPosition) {
case 'bottom':
case 'bottom-left':
return chartSize.height + ChartStyles_1.ChartCommonStyles.legend.margin * 2 + top + dy;
case 'right': {
// Legend height with padding
const legendDimensions = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps,
theme
});
const originX = chartSize.height / 2 + top;
const legendPadding = (legendDataArr) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0);
return originX - legendDimensions.height / 2 + legendPadding(legendData);
}
default:
return dy;
}
};
/**
* Returns x coordinate for pie legends
*
* @private Not intended as public API and subject to change
*/
const getPieLegendX = ({ dx = 0, height, legendData, legendOrientation, legendPosition, legendProps, padding, theme, width }) => {
const origin = (0, chart_origin_1.getPieOrigin)({ height, padding, width });
const radius = victory_core_1.Helpers.getRadius({ height, width, padding });
const legendDimensions = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps,
theme
});
switch (legendPosition) {
case 'bottom':
return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx;
case 'right':
return origin.x + ChartStyles_1.ChartCommonStyles.label.margin + dx + radius;
default:
return dx;
}
};
/**
* Returns y coordinate for pie legends
*
* @private Not intended as public API and subject to change
*/
const getPieLegendY = ({ dy = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => {
const origin = (0, chart_origin_1.getPieOrigin)({ height, padding, width });
const radius = victory_core_1.Helpers.getRadius({ height, width, padding });
switch (legendPosition) {
case 'bottom':
return origin.y + ChartStyles_1.ChartCommonStyles.legend.margin + radius + dy;
case 'right': {
// Legend height with padding
const legendDimensions = (0, exports.getLegendDimensions)({
legendData,
legendOrientation,
legendProps,
theme
});
const legendPadding = (legendDataArr) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0);
return origin.y - legendDimensions.height / 2 + legendPadding(legendData);
}
default:
return dy;
}
};
/**
* Returns an approximation of longest text width based on legend styles
*
* @private Not intended as public API and subject to change
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const getMaxLegendTextSize = ({ legendData, theme }) => {
const style = theme && theme.legend && theme.legend.style ? theme.legend.style.labels : undefined;
if (!(legendData && legendData.length)) {
return 0;
}
let result = '';
legendData.forEach((data) => {
if (data.name && data.name.length > result.length) {
result = data.name;
}
});
// The approximateTextSize function returns height and width, but Victory incorrectly typed it as number
const adjustedTextSize = victory_core_1.TextSize.approximateTextSize(result, Object.assign({}, style));
return adjustedTextSize.width;
};
//# sourceMappingURL=chart-legend.js.map